1/*- 2 * Copyright (c) 2000 Alfred Perlstein <alfred@freebsd.org> 3 * Copyright (c) 2000 Paul Saab <ps@freebsd.org> 4 * Copyright (c) 2000 John Baldwin <jhb@freebsd.org> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29#include <sys/cdefs.h>
| 1/*- 2 * Copyright (c) 2000 Alfred Perlstein <alfred@freebsd.org> 3 * Copyright (c) 2000 Paul Saab <ps@freebsd.org> 4 * Copyright (c) 2000 John Baldwin <jhb@freebsd.org> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29#include <sys/cdefs.h>
|
30__FBSDID("$FreeBSD: stable/11/sys/boot/i386/libi386/pxe.c 313355 2017-02-06 22:03:07Z tsoome $");
| 30__FBSDID("$FreeBSD: stable/11/sys/boot/i386/libi386/pxe.c 328889 2018-02-05 17:01:18Z kevans $");
|
31 32#include <stand.h> 33#include <string.h> 34#include <stdarg.h> 35 36#include <netinet/in_systm.h> 37#include <netinet/in.h> 38#include <netinet/udp.h> 39 40#include <net.h> 41#include <netif.h> 42#include <nfsv2.h> 43#include <iodesc.h> 44 45#include <bootp.h> 46#include <bootstrap.h> 47#include "btxv86.h" 48#include "pxe.h" 49 50/* 51 * Allocate the PXE buffers statically instead of sticking grimy fingers into 52 * BTX's private data area. The scratch buffer is used to send information to 53 * the PXE BIOS, and the data buffer is used to receive data from the PXE BIOS. 54 */ 55#define PXE_BUFFER_SIZE 0x2000 56#define PXE_TFTP_BUFFER_SIZE 512 57static char scratch_buffer[PXE_BUFFER_SIZE]; 58static char data_buffer[PXE_BUFFER_SIZE]; 59 60static pxenv_t *pxenv_p = NULL; /* PXENV+ */ 61static pxe_t *pxe_p = NULL; /* !PXE */ 62static BOOTPLAYER bootplayer; /* PXE Cached information. */ 63 64static int pxe_debug = 0; 65static int pxe_sock = -1; 66static int pxe_opens = 0; 67 68void pxe_enable(void *pxeinfo); 69static void (*pxe_call)(int func); 70static void pxenv_call(int func); 71static void bangpxe_call(int func); 72 73static int pxe_init(void); 74static int pxe_strategy(void *devdata, int flag, daddr_t dblk, 75 size_t size, char *buf, size_t *rsize); 76static int pxe_open(struct open_file *f, ...); 77static int pxe_close(struct open_file *f);
| 31 32#include <stand.h> 33#include <string.h> 34#include <stdarg.h> 35 36#include <netinet/in_systm.h> 37#include <netinet/in.h> 38#include <netinet/udp.h> 39 40#include <net.h> 41#include <netif.h> 42#include <nfsv2.h> 43#include <iodesc.h> 44 45#include <bootp.h> 46#include <bootstrap.h> 47#include "btxv86.h" 48#include "pxe.h" 49 50/* 51 * Allocate the PXE buffers statically instead of sticking grimy fingers into 52 * BTX's private data area. The scratch buffer is used to send information to 53 * the PXE BIOS, and the data buffer is used to receive data from the PXE BIOS. 54 */ 55#define PXE_BUFFER_SIZE 0x2000 56#define PXE_TFTP_BUFFER_SIZE 512 57static char scratch_buffer[PXE_BUFFER_SIZE]; 58static char data_buffer[PXE_BUFFER_SIZE]; 59 60static pxenv_t *pxenv_p = NULL; /* PXENV+ */ 61static pxe_t *pxe_p = NULL; /* !PXE */ 62static BOOTPLAYER bootplayer; /* PXE Cached information. */ 63 64static int pxe_debug = 0; 65static int pxe_sock = -1; 66static int pxe_opens = 0; 67 68void pxe_enable(void *pxeinfo); 69static void (*pxe_call)(int func); 70static void pxenv_call(int func); 71static void bangpxe_call(int func); 72 73static int pxe_init(void); 74static int pxe_strategy(void *devdata, int flag, daddr_t dblk, 75 size_t size, char *buf, size_t *rsize); 76static int pxe_open(struct open_file *f, ...); 77static int pxe_close(struct open_file *f);
|
78static void pxe_print(int verbose);
| 78static int pxe_print(int verbose);
|
79static void pxe_cleanup(void); 80static void pxe_setnfshandle(char *rootpath); 81 82static void pxe_perror(int error); 83static int pxe_netif_match(struct netif *nif, void *machdep_hint); 84static int pxe_netif_probe(struct netif *nif, void *machdep_hint); 85static void pxe_netif_init(struct iodesc *desc, void *machdep_hint); 86static int pxe_netif_get(struct iodesc *desc, void *pkt, size_t len, 87 time_t timeout); 88static int pxe_netif_put(struct iodesc *desc, void *pkt, size_t len); 89static void pxe_netif_end(struct netif *nif); 90 91#ifdef OLD_NFSV2 92int nfs_getrootfh(struct iodesc*, char*, u_char*); 93#else 94int nfs_getrootfh(struct iodesc*, char*, uint32_t*, u_char*); 95#endif 96 97extern struct netif_stats pxe_st[]; 98extern u_int16_t __bangpxeseg; 99extern u_int16_t __bangpxeoff; 100extern void __bangpxeentry(void); 101extern u_int16_t __pxenvseg; 102extern u_int16_t __pxenvoff; 103extern void __pxenventry(void); 104 105struct netif_dif pxe_ifs[] = { 106/* dif_unit dif_nsel dif_stats dif_private */ 107 {0, 1, &pxe_st[0], 0} 108}; 109 110struct netif_stats pxe_st[NENTS(pxe_ifs)]; 111 112struct netif_driver pxenetif = { 113 "pxenet", 114 pxe_netif_match, 115 pxe_netif_probe, 116 pxe_netif_init, 117 pxe_netif_get, 118 pxe_netif_put, 119 pxe_netif_end, 120 pxe_ifs, 121 NENTS(pxe_ifs) 122}; 123 124struct netif_driver *netif_drivers[] = { 125 &pxenetif, 126 NULL 127}; 128 129struct devsw pxedisk = { 130 "pxe", 131 DEVT_NET, 132 pxe_init, 133 pxe_strategy, 134 pxe_open, 135 pxe_close, 136 noioctl, 137 pxe_print, 138 pxe_cleanup 139}; 140 141/* 142 * This function is called by the loader to enable PXE support if we 143 * are booted by PXE. The passed in pointer is a pointer to the 144 * PXENV+ structure. 145 */ 146void 147pxe_enable(void *pxeinfo) 148{ 149 pxenv_p = (pxenv_t *)pxeinfo; 150 pxe_p = (pxe_t *)PTOV(pxenv_p->PXEPtr.segment * 16 + 151 pxenv_p->PXEPtr.offset); 152 pxe_call = NULL; 153} 154 155/* 156 * return true if pxe structures are found/initialized, 157 * also figures out our IP information via the pxe cached info struct 158 */ 159static int 160pxe_init(void) 161{ 162 t_PXENV_GET_CACHED_INFO *gci_p; 163 int counter; 164 uint8_t checksum; 165 uint8_t *checkptr; 166 167 if(pxenv_p == NULL) 168 return (0); 169 170 /* look for "PXENV+" */ 171 if (bcmp((void *)pxenv_p->Signature, S_SIZE("PXENV+"))) { 172 pxenv_p = NULL; 173 return (0); 174 } 175 176 /* make sure the size is something we can handle */ 177 if (pxenv_p->Length > sizeof(*pxenv_p)) { 178 printf("PXENV+ structure too large, ignoring\n"); 179 pxenv_p = NULL; 180 return (0); 181 } 182 183 /* 184 * do byte checksum: 185 * add up each byte in the structure, the total should be 0 186 */ 187 checksum = 0; 188 checkptr = (uint8_t *) pxenv_p; 189 for (counter = 0; counter < pxenv_p->Length; counter++) 190 checksum += *checkptr++; 191 if (checksum != 0) { 192 printf("PXENV+ structure failed checksum, ignoring\n"); 193 pxenv_p = NULL; 194 return (0); 195 } 196 197 198 /* 199 * PXENV+ passed, so use that if !PXE is not available or 200 * the checksum fails. 201 */ 202 pxe_call = pxenv_call; 203 if (pxenv_p->Version >= 0x0200) { 204 for (;;) { 205 if (bcmp((void *)pxe_p->Signature, S_SIZE("!PXE"))) { 206 pxe_p = NULL; 207 break; 208 } 209 checksum = 0; 210 checkptr = (uint8_t *)pxe_p; 211 for (counter = 0; counter < pxe_p->StructLength; 212 counter++) 213 checksum += *checkptr++; 214 if (checksum != 0) { 215 pxe_p = NULL; 216 break; 217 } 218 pxe_call = bangpxe_call; 219 break; 220 } 221 } 222 223 printf("\nPXE version %d.%d, real mode entry point ", 224 (uint8_t) (pxenv_p->Version >> 8), 225 (uint8_t) (pxenv_p->Version & 0xFF)); 226 if (pxe_call == bangpxe_call) 227 printf("@%04x:%04x\n", 228 pxe_p->EntryPointSP.segment, 229 pxe_p->EntryPointSP.offset); 230 else 231 printf("@%04x:%04x\n", 232 pxenv_p->RMEntry.segment, pxenv_p->RMEntry.offset); 233 234 gci_p = (t_PXENV_GET_CACHED_INFO *) scratch_buffer; 235 bzero(gci_p, sizeof(*gci_p)); 236 gci_p->PacketType = PXENV_PACKET_TYPE_BINL_REPLY; 237 pxe_call(PXENV_GET_CACHED_INFO); 238 if (gci_p->Status != 0) { 239 pxe_perror(gci_p->Status); 240 pxe_p = NULL; 241 return (0); 242 } 243 bcopy(PTOV((gci_p->Buffer.segment << 4) + gci_p->Buffer.offset), 244 &bootplayer, gci_p->BufferSize); 245 return (1); 246} 247 248 249static int 250pxe_strategy(void *devdata, int flag, daddr_t dblk, size_t size, 251 char *buf, size_t *rsize) 252{ 253 return (EIO); 254} 255 256static int 257pxe_open(struct open_file *f, ...) 258{ 259 va_list args; 260 char *devname; /* Device part of file name (or NULL). */ 261 char temp[FNAME_SIZE]; 262 int error = 0; 263 int i; 264 265 va_start(args, f); 266 devname = va_arg(args, char*); 267 va_end(args); 268 269 /* On first open, do netif open, mount, etc. */ 270 if (pxe_opens == 0) { 271 /* Find network interface. */ 272 if (pxe_sock < 0) { 273 pxe_sock = netif_open(devname); 274 if (pxe_sock < 0) { 275 printf("pxe_open: netif_open() failed\n"); 276 return (ENXIO); 277 } 278 if (pxe_debug) 279 printf("pxe_open: netif_open() succeeded\n"); 280 } 281 if (rootip.s_addr == 0) { 282 /* 283 * Do a bootp/dhcp request to find out where our 284 * NFS/TFTP server is. Even if we dont get back 285 * the proper information, fall back to the server 286 * which brought us to life and a default rootpath. 287 */ 288 bootp(pxe_sock, BOOTP_PXE); 289 if (rootip.s_addr == 0) 290 rootip.s_addr = bootplayer.sip; 291 292 netproto = NET_NFS; 293 if (tftpip.s_addr != 0) { 294 netproto = NET_TFTP; 295 rootip.s_addr = tftpip.s_addr; 296 } 297 298 if (netproto == NET_NFS && !rootpath[0]) 299 strcpy(rootpath, PXENFSROOTPATH); 300 301 for (i = 0; rootpath[i] != '\0' && i < FNAME_SIZE; i++) 302 if (rootpath[i] == ':') 303 break; 304 if (i && i != FNAME_SIZE && rootpath[i] == ':') { 305 rootpath[i++] = '\0'; 306 if (inet_addr(&rootpath[0]) != INADDR_NONE) 307 rootip.s_addr = inet_addr(&rootpath[0]); 308 bcopy(&rootpath[i], &temp[0], strlen(&rootpath[i])+1); 309 bcopy(&temp[0], &rootpath[0], strlen(&rootpath[i])+1); 310 } 311 setenv("boot.netif.ip", inet_ntoa(myip), 1); 312 setenv("boot.netif.netmask", intoa(netmask), 1); 313 setenv("boot.netif.gateway", inet_ntoa(gateip), 1); 314 setenv("boot.netif.server", inet_ntoa(rootip), 1); 315 if (bootplayer.Hardware == ETHER_TYPE) { 316 sprintf(temp, "%6D", bootplayer.CAddr, ":"); 317 setenv("boot.netif.hwaddr", temp, 1); 318 } 319 if (intf_mtu != 0) { 320 char mtu[16]; 321 sprintf(mtu, "%u", intf_mtu); 322 setenv("boot.netif.mtu", mtu, 1); 323 } 324 printf("pxe_open: server addr: %s\n", inet_ntoa(rootip)); 325 printf("pxe_open: server path: %s\n", rootpath); 326 printf("pxe_open: gateway ip: %s\n", inet_ntoa(gateip)); 327 328 if (netproto == NET_TFTP) { 329 setenv("boot.tftproot.server", inet_ntoa(rootip), 1); 330 setenv("boot.tftproot.path", rootpath, 1); 331 } else if (netproto == NET_NFS) { 332 setenv("boot.nfsroot.server", inet_ntoa(rootip), 1); 333 setenv("boot.nfsroot.path", rootpath, 1); 334 } 335 setenv("dhcp.host-name", hostname, 1); 336 337 setenv("pxeboot.ip", inet_ntoa(myip), 1); 338 if (bootplayer.Hardware == ETHER_TYPE) { 339 sprintf(temp, "%6D", bootplayer.CAddr, ":"); 340 setenv("pxeboot.hwaddr", temp, 1); 341 } 342 } 343 } 344 pxe_opens++; 345 f->f_devdata = &pxe_sock; 346 return (error); 347} 348 349static int 350pxe_close(struct open_file *f) 351{ 352 353#ifdef PXE_DEBUG 354 if (pxe_debug) 355 printf("pxe_close: opens=%d\n", pxe_opens); 356#endif 357 358 /* On last close, do netif close, etc. */ 359 f->f_devdata = NULL; 360 /* Extra close call? */ 361 if (pxe_opens <= 0) 362 return (0); 363 pxe_opens--; 364 /* Not last close? */ 365 if (pxe_opens > 0) 366 return(0); 367 368 if (netproto == NET_NFS) { 369 /* get an NFS filehandle for our root filesystem */ 370 pxe_setnfshandle(rootpath); 371 } 372 373 if (pxe_sock >= 0) { 374 375#ifdef PXE_DEBUG 376 if (pxe_debug) 377 printf("pxe_close: calling netif_close()\n"); 378#endif 379 netif_close(pxe_sock); 380 pxe_sock = -1; 381 } 382 return (0); 383} 384
| 79static void pxe_cleanup(void); 80static void pxe_setnfshandle(char *rootpath); 81 82static void pxe_perror(int error); 83static int pxe_netif_match(struct netif *nif, void *machdep_hint); 84static int pxe_netif_probe(struct netif *nif, void *machdep_hint); 85static void pxe_netif_init(struct iodesc *desc, void *machdep_hint); 86static int pxe_netif_get(struct iodesc *desc, void *pkt, size_t len, 87 time_t timeout); 88static int pxe_netif_put(struct iodesc *desc, void *pkt, size_t len); 89static void pxe_netif_end(struct netif *nif); 90 91#ifdef OLD_NFSV2 92int nfs_getrootfh(struct iodesc*, char*, u_char*); 93#else 94int nfs_getrootfh(struct iodesc*, char*, uint32_t*, u_char*); 95#endif 96 97extern struct netif_stats pxe_st[]; 98extern u_int16_t __bangpxeseg; 99extern u_int16_t __bangpxeoff; 100extern void __bangpxeentry(void); 101extern u_int16_t __pxenvseg; 102extern u_int16_t __pxenvoff; 103extern void __pxenventry(void); 104 105struct netif_dif pxe_ifs[] = { 106/* dif_unit dif_nsel dif_stats dif_private */ 107 {0, 1, &pxe_st[0], 0} 108}; 109 110struct netif_stats pxe_st[NENTS(pxe_ifs)]; 111 112struct netif_driver pxenetif = { 113 "pxenet", 114 pxe_netif_match, 115 pxe_netif_probe, 116 pxe_netif_init, 117 pxe_netif_get, 118 pxe_netif_put, 119 pxe_netif_end, 120 pxe_ifs, 121 NENTS(pxe_ifs) 122}; 123 124struct netif_driver *netif_drivers[] = { 125 &pxenetif, 126 NULL 127}; 128 129struct devsw pxedisk = { 130 "pxe", 131 DEVT_NET, 132 pxe_init, 133 pxe_strategy, 134 pxe_open, 135 pxe_close, 136 noioctl, 137 pxe_print, 138 pxe_cleanup 139}; 140 141/* 142 * This function is called by the loader to enable PXE support if we 143 * are booted by PXE. The passed in pointer is a pointer to the 144 * PXENV+ structure. 145 */ 146void 147pxe_enable(void *pxeinfo) 148{ 149 pxenv_p = (pxenv_t *)pxeinfo; 150 pxe_p = (pxe_t *)PTOV(pxenv_p->PXEPtr.segment * 16 + 151 pxenv_p->PXEPtr.offset); 152 pxe_call = NULL; 153} 154 155/* 156 * return true if pxe structures are found/initialized, 157 * also figures out our IP information via the pxe cached info struct 158 */ 159static int 160pxe_init(void) 161{ 162 t_PXENV_GET_CACHED_INFO *gci_p; 163 int counter; 164 uint8_t checksum; 165 uint8_t *checkptr; 166 167 if(pxenv_p == NULL) 168 return (0); 169 170 /* look for "PXENV+" */ 171 if (bcmp((void *)pxenv_p->Signature, S_SIZE("PXENV+"))) { 172 pxenv_p = NULL; 173 return (0); 174 } 175 176 /* make sure the size is something we can handle */ 177 if (pxenv_p->Length > sizeof(*pxenv_p)) { 178 printf("PXENV+ structure too large, ignoring\n"); 179 pxenv_p = NULL; 180 return (0); 181 } 182 183 /* 184 * do byte checksum: 185 * add up each byte in the structure, the total should be 0 186 */ 187 checksum = 0; 188 checkptr = (uint8_t *) pxenv_p; 189 for (counter = 0; counter < pxenv_p->Length; counter++) 190 checksum += *checkptr++; 191 if (checksum != 0) { 192 printf("PXENV+ structure failed checksum, ignoring\n"); 193 pxenv_p = NULL; 194 return (0); 195 } 196 197 198 /* 199 * PXENV+ passed, so use that if !PXE is not available or 200 * the checksum fails. 201 */ 202 pxe_call = pxenv_call; 203 if (pxenv_p->Version >= 0x0200) { 204 for (;;) { 205 if (bcmp((void *)pxe_p->Signature, S_SIZE("!PXE"))) { 206 pxe_p = NULL; 207 break; 208 } 209 checksum = 0; 210 checkptr = (uint8_t *)pxe_p; 211 for (counter = 0; counter < pxe_p->StructLength; 212 counter++) 213 checksum += *checkptr++; 214 if (checksum != 0) { 215 pxe_p = NULL; 216 break; 217 } 218 pxe_call = bangpxe_call; 219 break; 220 } 221 } 222 223 printf("\nPXE version %d.%d, real mode entry point ", 224 (uint8_t) (pxenv_p->Version >> 8), 225 (uint8_t) (pxenv_p->Version & 0xFF)); 226 if (pxe_call == bangpxe_call) 227 printf("@%04x:%04x\n", 228 pxe_p->EntryPointSP.segment, 229 pxe_p->EntryPointSP.offset); 230 else 231 printf("@%04x:%04x\n", 232 pxenv_p->RMEntry.segment, pxenv_p->RMEntry.offset); 233 234 gci_p = (t_PXENV_GET_CACHED_INFO *) scratch_buffer; 235 bzero(gci_p, sizeof(*gci_p)); 236 gci_p->PacketType = PXENV_PACKET_TYPE_BINL_REPLY; 237 pxe_call(PXENV_GET_CACHED_INFO); 238 if (gci_p->Status != 0) { 239 pxe_perror(gci_p->Status); 240 pxe_p = NULL; 241 return (0); 242 } 243 bcopy(PTOV((gci_p->Buffer.segment << 4) + gci_p->Buffer.offset), 244 &bootplayer, gci_p->BufferSize); 245 return (1); 246} 247 248 249static int 250pxe_strategy(void *devdata, int flag, daddr_t dblk, size_t size, 251 char *buf, size_t *rsize) 252{ 253 return (EIO); 254} 255 256static int 257pxe_open(struct open_file *f, ...) 258{ 259 va_list args; 260 char *devname; /* Device part of file name (or NULL). */ 261 char temp[FNAME_SIZE]; 262 int error = 0; 263 int i; 264 265 va_start(args, f); 266 devname = va_arg(args, char*); 267 va_end(args); 268 269 /* On first open, do netif open, mount, etc. */ 270 if (pxe_opens == 0) { 271 /* Find network interface. */ 272 if (pxe_sock < 0) { 273 pxe_sock = netif_open(devname); 274 if (pxe_sock < 0) { 275 printf("pxe_open: netif_open() failed\n"); 276 return (ENXIO); 277 } 278 if (pxe_debug) 279 printf("pxe_open: netif_open() succeeded\n"); 280 } 281 if (rootip.s_addr == 0) { 282 /* 283 * Do a bootp/dhcp request to find out where our 284 * NFS/TFTP server is. Even if we dont get back 285 * the proper information, fall back to the server 286 * which brought us to life and a default rootpath. 287 */ 288 bootp(pxe_sock, BOOTP_PXE); 289 if (rootip.s_addr == 0) 290 rootip.s_addr = bootplayer.sip; 291 292 netproto = NET_NFS; 293 if (tftpip.s_addr != 0) { 294 netproto = NET_TFTP; 295 rootip.s_addr = tftpip.s_addr; 296 } 297 298 if (netproto == NET_NFS && !rootpath[0]) 299 strcpy(rootpath, PXENFSROOTPATH); 300 301 for (i = 0; rootpath[i] != '\0' && i < FNAME_SIZE; i++) 302 if (rootpath[i] == ':') 303 break; 304 if (i && i != FNAME_SIZE && rootpath[i] == ':') { 305 rootpath[i++] = '\0'; 306 if (inet_addr(&rootpath[0]) != INADDR_NONE) 307 rootip.s_addr = inet_addr(&rootpath[0]); 308 bcopy(&rootpath[i], &temp[0], strlen(&rootpath[i])+1); 309 bcopy(&temp[0], &rootpath[0], strlen(&rootpath[i])+1); 310 } 311 setenv("boot.netif.ip", inet_ntoa(myip), 1); 312 setenv("boot.netif.netmask", intoa(netmask), 1); 313 setenv("boot.netif.gateway", inet_ntoa(gateip), 1); 314 setenv("boot.netif.server", inet_ntoa(rootip), 1); 315 if (bootplayer.Hardware == ETHER_TYPE) { 316 sprintf(temp, "%6D", bootplayer.CAddr, ":"); 317 setenv("boot.netif.hwaddr", temp, 1); 318 } 319 if (intf_mtu != 0) { 320 char mtu[16]; 321 sprintf(mtu, "%u", intf_mtu); 322 setenv("boot.netif.mtu", mtu, 1); 323 } 324 printf("pxe_open: server addr: %s\n", inet_ntoa(rootip)); 325 printf("pxe_open: server path: %s\n", rootpath); 326 printf("pxe_open: gateway ip: %s\n", inet_ntoa(gateip)); 327 328 if (netproto == NET_TFTP) { 329 setenv("boot.tftproot.server", inet_ntoa(rootip), 1); 330 setenv("boot.tftproot.path", rootpath, 1); 331 } else if (netproto == NET_NFS) { 332 setenv("boot.nfsroot.server", inet_ntoa(rootip), 1); 333 setenv("boot.nfsroot.path", rootpath, 1); 334 } 335 setenv("dhcp.host-name", hostname, 1); 336 337 setenv("pxeboot.ip", inet_ntoa(myip), 1); 338 if (bootplayer.Hardware == ETHER_TYPE) { 339 sprintf(temp, "%6D", bootplayer.CAddr, ":"); 340 setenv("pxeboot.hwaddr", temp, 1); 341 } 342 } 343 } 344 pxe_opens++; 345 f->f_devdata = &pxe_sock; 346 return (error); 347} 348 349static int 350pxe_close(struct open_file *f) 351{ 352 353#ifdef PXE_DEBUG 354 if (pxe_debug) 355 printf("pxe_close: opens=%d\n", pxe_opens); 356#endif 357 358 /* On last close, do netif close, etc. */ 359 f->f_devdata = NULL; 360 /* Extra close call? */ 361 if (pxe_opens <= 0) 362 return (0); 363 pxe_opens--; 364 /* Not last close? */ 365 if (pxe_opens > 0) 366 return(0); 367 368 if (netproto == NET_NFS) { 369 /* get an NFS filehandle for our root filesystem */ 370 pxe_setnfshandle(rootpath); 371 } 372 373 if (pxe_sock >= 0) { 374 375#ifdef PXE_DEBUG 376 if (pxe_debug) 377 printf("pxe_close: calling netif_close()\n"); 378#endif 379 netif_close(pxe_sock); 380 pxe_sock = -1; 381 } 382 return (0); 383} 384
|
385static void
| 385static int
|
386pxe_print(int verbose) 387{
| 386pxe_print(int verbose) 387{
|
388
| 388 char line[255];
|
389 if (pxe_call == NULL)
| 389 if (pxe_call == NULL)
|
390 return;
| 390 return (0);
|
391
| 391
|
392 printf(" pxe0: %s:%s\n", inet_ntoa(rootip), rootpath);
| 392 printf("%s devices:", pxedisk.dv_name); 393 if (pager_output("\n") != 0) 394 return (1); 395 if (verbose) { 396 snprintf(line, sizeof(line), " pxe0: %s:%s\n", 397 inet_ntoa(rootip), rootpath); 398 } else { 399 snprintf(line, sizeof(line), " pxe0:\n"); 400 } 401 return (pager_output(line));
|
393} 394 395static void 396pxe_cleanup(void) 397{ 398#ifdef PXE_DEBUG 399 t_PXENV_UNLOAD_STACK *unload_stack_p = 400 (t_PXENV_UNLOAD_STACK *)scratch_buffer; 401 t_PXENV_UNDI_SHUTDOWN *undi_shutdown_p = 402 (t_PXENV_UNDI_SHUTDOWN *)scratch_buffer; 403#endif 404 405 if (pxe_call == NULL) 406 return; 407 408 pxe_call(PXENV_UNDI_SHUTDOWN); 409 410#ifdef PXE_DEBUG 411 if (pxe_debug && undi_shutdown_p->Status != 0) 412 printf("pxe_cleanup: UNDI_SHUTDOWN failed %x\n", 413 undi_shutdown_p->Status); 414#endif 415 416 pxe_call(PXENV_UNLOAD_STACK); 417 418#ifdef PXE_DEBUG 419 if (pxe_debug && unload_stack_p->Status != 0) 420 printf("pxe_cleanup: UNLOAD_STACK failed %x\n", 421 unload_stack_p->Status); 422#endif 423} 424 425void 426pxe_perror(int err) 427{ 428 return; 429} 430 431/* 432 * Reach inside the libstand NFS code and dig out an NFS handle 433 * for the root filesystem. 434 */ 435#ifdef OLD_NFSV2 436struct nfs_iodesc { 437 struct iodesc *iodesc; 438 off_t off; 439 u_char fh[NFS_FHSIZE]; 440 /* structure truncated here */ 441}; 442extern struct nfs_iodesc nfs_root_node; 443extern int rpc_port; 444 445static void 446pxe_rpcmountcall() 447{ 448 struct iodesc *d; 449 int error; 450 451 if (!(d = socktodesc(pxe_sock))) 452 return; 453 d->myport = htons(--rpc_port); 454 d->destip = rootip; 455 if ((error = nfs_getrootfh(d, rootpath, nfs_root_node.fh)) != 0) 456 printf("NFS MOUNT RPC error: %d\n", error); 457 nfs_root_node.iodesc = d; 458} 459 460static void 461pxe_setnfshandle(char *rootpath) 462{ 463 int i; 464 u_char *fh; 465 char buf[2 * NFS_FHSIZE + 3], *cp; 466 467 /* 468 * If NFS files were never opened, we need to do mount call 469 * ourselves. Use nfs_root_node.iodesc as flag indicating 470 * previous NFS usage. 471 */ 472 if (nfs_root_node.iodesc == NULL) 473 pxe_rpcmountcall(); 474 475 fh = &nfs_root_node.fh[0]; 476 buf[0] = 'X'; 477 cp = &buf[1]; 478 for (i = 0; i < NFS_FHSIZE; i++, cp += 2) 479 sprintf(cp, "%02x", fh[i]); 480 sprintf(cp, "X"); 481 setenv("boot.nfsroot.nfshandle", buf, 1); 482} 483#else /* !OLD_NFSV2 */ 484 485#define NFS_V3MAXFHSIZE 64 486 487struct nfs_iodesc { 488 struct iodesc *iodesc; 489 off_t off; 490 uint32_t fhsize; 491 u_char fh[NFS_V3MAXFHSIZE]; 492 /* structure truncated */ 493}; 494extern struct nfs_iodesc nfs_root_node; 495extern int rpc_port; 496 497static void 498pxe_rpcmountcall() 499{ 500 struct iodesc *d; 501 int error; 502 503 if (!(d = socktodesc(pxe_sock))) 504 return; 505 d->myport = htons(--rpc_port); 506 d->destip = rootip; 507 if ((error = nfs_getrootfh(d, rootpath, &nfs_root_node.fhsize, 508 nfs_root_node.fh)) != 0) { 509 printf("NFS MOUNT RPC error: %d\n", error); 510 nfs_root_node.fhsize = 0; 511 } 512 nfs_root_node.iodesc = d; 513} 514 515static void 516pxe_setnfshandle(char *rootpath) 517{ 518 int i; 519 u_char *fh; 520 char buf[2 * NFS_V3MAXFHSIZE + 3], *cp; 521 522 /* 523 * If NFS files were never opened, we need to do mount call 524 * ourselves. Use nfs_root_node.iodesc as flag indicating 525 * previous NFS usage. 526 */ 527 if (nfs_root_node.iodesc == NULL) 528 pxe_rpcmountcall(); 529 530 fh = &nfs_root_node.fh[0]; 531 buf[0] = 'X'; 532 cp = &buf[1]; 533 for (i = 0; i < nfs_root_node.fhsize; i++, cp += 2) 534 sprintf(cp, "%02x", fh[i]); 535 sprintf(cp, "X"); 536 setenv("boot.nfsroot.nfshandle", buf, 1); 537 sprintf(buf, "%d", nfs_root_node.fhsize); 538 setenv("boot.nfsroot.nfshandlelen", buf, 1); 539} 540#endif /* OLD_NFSV2 */ 541 542void 543pxenv_call(int func) 544{ 545#ifdef PXE_DEBUG 546 if (pxe_debug) 547 printf("pxenv_call %x\n", func); 548#endif 549 550 bzero(&v86, sizeof(v86)); 551 bzero(data_buffer, sizeof(data_buffer)); 552 553 __pxenvseg = pxenv_p->RMEntry.segment; 554 __pxenvoff = pxenv_p->RMEntry.offset; 555 556 v86.ctl = V86_ADDR | V86_CALLF | V86_FLAGS; 557 v86.es = VTOPSEG(scratch_buffer); 558 v86.edi = VTOPOFF(scratch_buffer); 559 v86.addr = (VTOPSEG(__pxenventry) << 16) | VTOPOFF(__pxenventry); 560 v86.ebx = func; 561 v86int(); 562 v86.ctl = V86_FLAGS; 563} 564 565void 566bangpxe_call(int func) 567{ 568#ifdef PXE_DEBUG 569 if (pxe_debug) 570 printf("bangpxe_call %x\n", func); 571#endif 572 573 bzero(&v86, sizeof(v86)); 574 bzero(data_buffer, sizeof(data_buffer)); 575 576 __bangpxeseg = pxe_p->EntryPointSP.segment; 577 __bangpxeoff = pxe_p->EntryPointSP.offset; 578 579 v86.ctl = V86_ADDR | V86_CALLF | V86_FLAGS; 580 v86.edx = VTOPSEG(scratch_buffer); 581 v86.eax = VTOPOFF(scratch_buffer); 582 v86.addr = (VTOPSEG(__bangpxeentry) << 16) | VTOPOFF(__bangpxeentry); 583 v86.ebx = func; 584 v86int(); 585 v86.ctl = V86_FLAGS; 586} 587 588 589time_t 590getsecs() 591{ 592 time_t n = 0; 593 time(&n); 594 return n; 595} 596 597static int 598pxe_netif_match(struct netif *nif, void *machdep_hint) 599{ 600 return 1; 601} 602 603 604static int 605pxe_netif_probe(struct netif *nif, void *machdep_hint) 606{ 607 t_PXENV_UDP_OPEN *udpopen_p = (t_PXENV_UDP_OPEN *)scratch_buffer; 608 609 if (pxe_call == NULL) 610 return -1; 611 612 bzero(udpopen_p, sizeof(*udpopen_p)); 613 udpopen_p->src_ip = bootplayer.yip; 614 pxe_call(PXENV_UDP_OPEN); 615 616 if (udpopen_p->status != 0) { 617 printf("pxe_netif_probe: failed %x\n", udpopen_p->status); 618 return -1; 619 } 620 return 0; 621} 622 623static void 624pxe_netif_end(struct netif *nif) 625{ 626 t_PXENV_UDP_CLOSE *udpclose_p = (t_PXENV_UDP_CLOSE *)scratch_buffer; 627 bzero(udpclose_p, sizeof(*udpclose_p)); 628 629 pxe_call(PXENV_UDP_CLOSE); 630 if (udpclose_p->status != 0) 631 printf("pxe_end failed %x\n", udpclose_p->status); 632} 633 634static void 635pxe_netif_init(struct iodesc *desc, void *machdep_hint) 636{ 637 int i; 638 for (i = 0; i < 6; ++i) 639 desc->myea[i] = bootplayer.CAddr[i]; 640 desc->xid = bootplayer.ident; 641} 642 643static int 644pxe_netif_get(struct iodesc *desc, void *pkt, size_t len, time_t timeout) 645{ 646 return len; 647} 648 649static int 650pxe_netif_put(struct iodesc *desc, void *pkt, size_t len) 651{ 652 return len; 653} 654 655ssize_t 656sendudp(struct iodesc *h, void *pkt, size_t len) 657{ 658 t_PXENV_UDP_WRITE *udpwrite_p = (t_PXENV_UDP_WRITE *)scratch_buffer; 659 bzero(udpwrite_p, sizeof(*udpwrite_p)); 660 661 udpwrite_p->ip = h->destip.s_addr; 662 udpwrite_p->dst_port = h->destport; 663 udpwrite_p->src_port = h->myport; 664 udpwrite_p->buffer_size = len; 665 udpwrite_p->buffer.segment = VTOPSEG(pkt); 666 udpwrite_p->buffer.offset = VTOPOFF(pkt); 667 668 if (netmask == 0 || SAMENET(myip, h->destip, netmask)) 669 udpwrite_p->gw = 0; 670 else 671 udpwrite_p->gw = gateip.s_addr; 672 673 pxe_call(PXENV_UDP_WRITE); 674 675#if 0 676 /* XXX - I dont know why we need this. */ 677 delay(1000); 678#endif 679 if (udpwrite_p->status != 0) { 680 /* XXX: This happens a lot. It shouldn't. */ 681 if (udpwrite_p->status != 1) 682 printf("sendudp failed %x\n", udpwrite_p->status); 683 return -1; 684 } 685 return len; 686} 687 688ssize_t 689readudp(struct iodesc *h, void *pkt, size_t len, time_t timeout) 690{ 691 t_PXENV_UDP_READ *udpread_p = (t_PXENV_UDP_READ *)scratch_buffer; 692 struct udphdr *uh = NULL; 693 694 uh = (struct udphdr *) pkt - 1; 695 bzero(udpread_p, sizeof(*udpread_p)); 696 697 udpread_p->dest_ip = h->myip.s_addr; 698 udpread_p->d_port = h->myport; 699 udpread_p->buffer_size = len; 700 udpread_p->buffer.segment = VTOPSEG(data_buffer); 701 udpread_p->buffer.offset = VTOPOFF(data_buffer); 702 703 pxe_call(PXENV_UDP_READ); 704 705#if 0 706 /* XXX - I dont know why we need this. */ 707 delay(1000); 708#endif 709 if (udpread_p->status != 0) { 710 /* XXX: This happens a lot. It shouldn't. */ 711 if (udpread_p->status != 1) 712 printf("readudp failed %x\n", udpread_p->status); 713 return -1; 714 } 715 bcopy(data_buffer, pkt, udpread_p->buffer_size); 716 uh->uh_sport = udpread_p->s_port; 717 return udpread_p->buffer_size; 718}
| 402} 403 404static void 405pxe_cleanup(void) 406{ 407#ifdef PXE_DEBUG 408 t_PXENV_UNLOAD_STACK *unload_stack_p = 409 (t_PXENV_UNLOAD_STACK *)scratch_buffer; 410 t_PXENV_UNDI_SHUTDOWN *undi_shutdown_p = 411 (t_PXENV_UNDI_SHUTDOWN *)scratch_buffer; 412#endif 413 414 if (pxe_call == NULL) 415 return; 416 417 pxe_call(PXENV_UNDI_SHUTDOWN); 418 419#ifdef PXE_DEBUG 420 if (pxe_debug && undi_shutdown_p->Status != 0) 421 printf("pxe_cleanup: UNDI_SHUTDOWN failed %x\n", 422 undi_shutdown_p->Status); 423#endif 424 425 pxe_call(PXENV_UNLOAD_STACK); 426 427#ifdef PXE_DEBUG 428 if (pxe_debug && unload_stack_p->Status != 0) 429 printf("pxe_cleanup: UNLOAD_STACK failed %x\n", 430 unload_stack_p->Status); 431#endif 432} 433 434void 435pxe_perror(int err) 436{ 437 return; 438} 439 440/* 441 * Reach inside the libstand NFS code and dig out an NFS handle 442 * for the root filesystem. 443 */ 444#ifdef OLD_NFSV2 445struct nfs_iodesc { 446 struct iodesc *iodesc; 447 off_t off; 448 u_char fh[NFS_FHSIZE]; 449 /* structure truncated here */ 450}; 451extern struct nfs_iodesc nfs_root_node; 452extern int rpc_port; 453 454static void 455pxe_rpcmountcall() 456{ 457 struct iodesc *d; 458 int error; 459 460 if (!(d = socktodesc(pxe_sock))) 461 return; 462 d->myport = htons(--rpc_port); 463 d->destip = rootip; 464 if ((error = nfs_getrootfh(d, rootpath, nfs_root_node.fh)) != 0) 465 printf("NFS MOUNT RPC error: %d\n", error); 466 nfs_root_node.iodesc = d; 467} 468 469static void 470pxe_setnfshandle(char *rootpath) 471{ 472 int i; 473 u_char *fh; 474 char buf[2 * NFS_FHSIZE + 3], *cp; 475 476 /* 477 * If NFS files were never opened, we need to do mount call 478 * ourselves. Use nfs_root_node.iodesc as flag indicating 479 * previous NFS usage. 480 */ 481 if (nfs_root_node.iodesc == NULL) 482 pxe_rpcmountcall(); 483 484 fh = &nfs_root_node.fh[0]; 485 buf[0] = 'X'; 486 cp = &buf[1]; 487 for (i = 0; i < NFS_FHSIZE; i++, cp += 2) 488 sprintf(cp, "%02x", fh[i]); 489 sprintf(cp, "X"); 490 setenv("boot.nfsroot.nfshandle", buf, 1); 491} 492#else /* !OLD_NFSV2 */ 493 494#define NFS_V3MAXFHSIZE 64 495 496struct nfs_iodesc { 497 struct iodesc *iodesc; 498 off_t off; 499 uint32_t fhsize; 500 u_char fh[NFS_V3MAXFHSIZE]; 501 /* structure truncated */ 502}; 503extern struct nfs_iodesc nfs_root_node; 504extern int rpc_port; 505 506static void 507pxe_rpcmountcall() 508{ 509 struct iodesc *d; 510 int error; 511 512 if (!(d = socktodesc(pxe_sock))) 513 return; 514 d->myport = htons(--rpc_port); 515 d->destip = rootip; 516 if ((error = nfs_getrootfh(d, rootpath, &nfs_root_node.fhsize, 517 nfs_root_node.fh)) != 0) { 518 printf("NFS MOUNT RPC error: %d\n", error); 519 nfs_root_node.fhsize = 0; 520 } 521 nfs_root_node.iodesc = d; 522} 523 524static void 525pxe_setnfshandle(char *rootpath) 526{ 527 int i; 528 u_char *fh; 529 char buf[2 * NFS_V3MAXFHSIZE + 3], *cp; 530 531 /* 532 * If NFS files were never opened, we need to do mount call 533 * ourselves. Use nfs_root_node.iodesc as flag indicating 534 * previous NFS usage. 535 */ 536 if (nfs_root_node.iodesc == NULL) 537 pxe_rpcmountcall(); 538 539 fh = &nfs_root_node.fh[0]; 540 buf[0] = 'X'; 541 cp = &buf[1]; 542 for (i = 0; i < nfs_root_node.fhsize; i++, cp += 2) 543 sprintf(cp, "%02x", fh[i]); 544 sprintf(cp, "X"); 545 setenv("boot.nfsroot.nfshandle", buf, 1); 546 sprintf(buf, "%d", nfs_root_node.fhsize); 547 setenv("boot.nfsroot.nfshandlelen", buf, 1); 548} 549#endif /* OLD_NFSV2 */ 550 551void 552pxenv_call(int func) 553{ 554#ifdef PXE_DEBUG 555 if (pxe_debug) 556 printf("pxenv_call %x\n", func); 557#endif 558 559 bzero(&v86, sizeof(v86)); 560 bzero(data_buffer, sizeof(data_buffer)); 561 562 __pxenvseg = pxenv_p->RMEntry.segment; 563 __pxenvoff = pxenv_p->RMEntry.offset; 564 565 v86.ctl = V86_ADDR | V86_CALLF | V86_FLAGS; 566 v86.es = VTOPSEG(scratch_buffer); 567 v86.edi = VTOPOFF(scratch_buffer); 568 v86.addr = (VTOPSEG(__pxenventry) << 16) | VTOPOFF(__pxenventry); 569 v86.ebx = func; 570 v86int(); 571 v86.ctl = V86_FLAGS; 572} 573 574void 575bangpxe_call(int func) 576{ 577#ifdef PXE_DEBUG 578 if (pxe_debug) 579 printf("bangpxe_call %x\n", func); 580#endif 581 582 bzero(&v86, sizeof(v86)); 583 bzero(data_buffer, sizeof(data_buffer)); 584 585 __bangpxeseg = pxe_p->EntryPointSP.segment; 586 __bangpxeoff = pxe_p->EntryPointSP.offset; 587 588 v86.ctl = V86_ADDR | V86_CALLF | V86_FLAGS; 589 v86.edx = VTOPSEG(scratch_buffer); 590 v86.eax = VTOPOFF(scratch_buffer); 591 v86.addr = (VTOPSEG(__bangpxeentry) << 16) | VTOPOFF(__bangpxeentry); 592 v86.ebx = func; 593 v86int(); 594 v86.ctl = V86_FLAGS; 595} 596 597 598time_t 599getsecs() 600{ 601 time_t n = 0; 602 time(&n); 603 return n; 604} 605 606static int 607pxe_netif_match(struct netif *nif, void *machdep_hint) 608{ 609 return 1; 610} 611 612 613static int 614pxe_netif_probe(struct netif *nif, void *machdep_hint) 615{ 616 t_PXENV_UDP_OPEN *udpopen_p = (t_PXENV_UDP_OPEN *)scratch_buffer; 617 618 if (pxe_call == NULL) 619 return -1; 620 621 bzero(udpopen_p, sizeof(*udpopen_p)); 622 udpopen_p->src_ip = bootplayer.yip; 623 pxe_call(PXENV_UDP_OPEN); 624 625 if (udpopen_p->status != 0) { 626 printf("pxe_netif_probe: failed %x\n", udpopen_p->status); 627 return -1; 628 } 629 return 0; 630} 631 632static void 633pxe_netif_end(struct netif *nif) 634{ 635 t_PXENV_UDP_CLOSE *udpclose_p = (t_PXENV_UDP_CLOSE *)scratch_buffer; 636 bzero(udpclose_p, sizeof(*udpclose_p)); 637 638 pxe_call(PXENV_UDP_CLOSE); 639 if (udpclose_p->status != 0) 640 printf("pxe_end failed %x\n", udpclose_p->status); 641} 642 643static void 644pxe_netif_init(struct iodesc *desc, void *machdep_hint) 645{ 646 int i; 647 for (i = 0; i < 6; ++i) 648 desc->myea[i] = bootplayer.CAddr[i]; 649 desc->xid = bootplayer.ident; 650} 651 652static int 653pxe_netif_get(struct iodesc *desc, void *pkt, size_t len, time_t timeout) 654{ 655 return len; 656} 657 658static int 659pxe_netif_put(struct iodesc *desc, void *pkt, size_t len) 660{ 661 return len; 662} 663 664ssize_t 665sendudp(struct iodesc *h, void *pkt, size_t len) 666{ 667 t_PXENV_UDP_WRITE *udpwrite_p = (t_PXENV_UDP_WRITE *)scratch_buffer; 668 bzero(udpwrite_p, sizeof(*udpwrite_p)); 669 670 udpwrite_p->ip = h->destip.s_addr; 671 udpwrite_p->dst_port = h->destport; 672 udpwrite_p->src_port = h->myport; 673 udpwrite_p->buffer_size = len; 674 udpwrite_p->buffer.segment = VTOPSEG(pkt); 675 udpwrite_p->buffer.offset = VTOPOFF(pkt); 676 677 if (netmask == 0 || SAMENET(myip, h->destip, netmask)) 678 udpwrite_p->gw = 0; 679 else 680 udpwrite_p->gw = gateip.s_addr; 681 682 pxe_call(PXENV_UDP_WRITE); 683 684#if 0 685 /* XXX - I dont know why we need this. */ 686 delay(1000); 687#endif 688 if (udpwrite_p->status != 0) { 689 /* XXX: This happens a lot. It shouldn't. */ 690 if (udpwrite_p->status != 1) 691 printf("sendudp failed %x\n", udpwrite_p->status); 692 return -1; 693 } 694 return len; 695} 696 697ssize_t 698readudp(struct iodesc *h, void *pkt, size_t len, time_t timeout) 699{ 700 t_PXENV_UDP_READ *udpread_p = (t_PXENV_UDP_READ *)scratch_buffer; 701 struct udphdr *uh = NULL; 702 703 uh = (struct udphdr *) pkt - 1; 704 bzero(udpread_p, sizeof(*udpread_p)); 705 706 udpread_p->dest_ip = h->myip.s_addr; 707 udpread_p->d_port = h->myport; 708 udpread_p->buffer_size = len; 709 udpread_p->buffer.segment = VTOPSEG(data_buffer); 710 udpread_p->buffer.offset = VTOPOFF(data_buffer); 711 712 pxe_call(PXENV_UDP_READ); 713 714#if 0 715 /* XXX - I dont know why we need this. */ 716 delay(1000); 717#endif 718 if (udpread_p->status != 0) { 719 /* XXX: This happens a lot. It shouldn't. */ 720 if (udpread_p->status != 1) 721 printf("readudp failed %x\n", udpread_p->status); 722 return -1; 723 } 724 bcopy(data_buffer, pkt, udpread_p->buffer_size); 725 uh->uh_sport = udpread_p->s_port; 726 return udpread_p->buffer_size; 727}
|