pxe.c (58993) | pxe.c (59087) |
---|---|
1/* 2 * Copyright (c) 2000 Alfred Perlstein <alfred@freebsd.org> 3 * All rights reserved. 4 * Copyright (c) 2000 Paul Saab <ps@freebsd.org> 5 * All rights reserved. 6 * Copyright (c) 2000 John Baldwin <jhb@freebsd.org> 7 * All rights reserved. 8 * --- 13 unchanged lines hidden (view full) --- 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 * | 1/* 2 * Copyright (c) 2000 Alfred Perlstein <alfred@freebsd.org> 3 * All rights reserved. 4 * Copyright (c) 2000 Paul Saab <ps@freebsd.org> 5 * All rights reserved. 6 * Copyright (c) 2000 John Baldwin <jhb@freebsd.org> 7 * All rights reserved. 8 * --- 13 unchanged lines hidden (view full) --- 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 * |
30 * $FreeBSD: head/sys/boot/i386/libi386/pxe.c 58993 2000-04-04 00:38:59Z ps $ | 30 * $FreeBSD: head/sys/boot/i386/libi386/pxe.c 59087 2000-04-08 01:22:14Z ps $ |
31 */ 32 33#include <stand.h> 34 | 31 */ 32 33#include <stand.h> 34 |
35#include <netinet/in_systm.h> 36#include <netinet/in.h> 37#include <netinet/udp.h> 38#include <netinet/ip.h> 39 |
|
35#include <sys/reboot.h> 36#include <string.h> 37#include <sys/reboot.h> 38#include <arpa/tftp.h> 39 | 40#include <sys/reboot.h> 41#include <string.h> 42#include <sys/reboot.h> 43#include <arpa/tftp.h> 44 |
45#include <net.h> 46#include <netif.h> 47 |
|
40#include <stdarg.h> 41 42#include <bootstrap.h> 43#include "btxv86.h" 44#include "pxe.h" 45 46/* 47 * Allocate the PXE buffers statically instead of sticking grimy fingers into 48 * BTX's private data area. The scratch buffer is used to send information to 49 * the PXE BIOS, and the data buffer is used to receive data from the PXE BIOS. 50 */ 51#define PXE_BUFFER_SIZE 0x2000 52#define PXE_TFTP_BUFFER_SIZE 512 53static char scratch_buffer[PXE_BUFFER_SIZE]; 54static char data_buffer[PXE_BUFFER_SIZE]; 55 | 48#include <stdarg.h> 49 50#include <bootstrap.h> 51#include "btxv86.h" 52#include "pxe.h" 53 54/* 55 * Allocate the PXE buffers statically instead of sticking grimy fingers into 56 * BTX's private data area. The scratch buffer is used to send information to 57 * the PXE BIOS, and the data buffer is used to receive data from the PXE BIOS. 58 */ 59#define PXE_BUFFER_SIZE 0x2000 60#define PXE_TFTP_BUFFER_SIZE 512 61static char scratch_buffer[PXE_BUFFER_SIZE]; 62static char data_buffer[PXE_BUFFER_SIZE]; 63 |
56static uint32_t myip; /* my IP address */ 57static uint32_t serverip; /* where I got my initial bootstrap from */ 58static uint32_t secondip; /* where I should go to get the rest of my boot files */ 59static char *servername = NULL; /* name of server I DHCP'd from */ 60static char *bootfile = NULL; /* name of file that I booted with */ 61static uint16_t pxe_return_status; 62static uint16_t pxe_open_status; | |
63static pxenv_t *pxenv_p = NULL; /* PXENV+ */ | 64static pxenv_t *pxenv_p = NULL; /* PXENV+ */ |
64static pxe_t *pxe_p = NULL; /* !PXE */ | 65static BOOTPLAYER bootplayer; /* PXE Cached information. */ |
65 | 66 |
67static int debug = 0; 68static int pxe_sock = -1; 69static int pxe_opens = 0; 70 |
|
66void pxe_enable(void *pxeinfo); | 71void pxe_enable(void *pxeinfo); |
72void pxe_call(int func); 73 |
|
67static int pxe_init(void); | 74static int pxe_init(void); |
68static int pxe_strategy(void *devdata, int flag, daddr_t dblk, size_t size, 69 void *buf, size_t *rsize); | 75static int pxe_strategy(void *devdata, int flag, daddr_t dblk, 76 size_t size, void *buf, size_t *rsize); |
70static int pxe_open(struct open_file *f, ...); 71static int pxe_close(struct open_file *f); 72static void pxe_print(int verbose); 73 74static void pxe_perror(int error); | 77static int pxe_open(struct open_file *f, ...); 78static int pxe_close(struct open_file *f); 79static void pxe_print(int verbose); 80 81static void pxe_perror(int error); |
75void pxe_call(int func); | 82static int pxe_netif_match(struct netif *nif, void *machdep_hint); 83static int pxe_netif_probe(struct netif *nif, void *machdep_hint); 84static void pxe_netif_init(struct iodesc *desc, void *machdep_hint); 85static int pxe_netif_get(struct iodesc *desc, void *pkt, size_t len, 86 time_t timeout); 87static int pxe_netif_put(struct iodesc *desc, void *pkt, size_t len); 88static void pxe_netif_end(struct netif *nif); |
76 | 89 |
77static int pxe_fs_open(const char *path, struct open_file *f); 78static int pxe_fs_close(struct open_file *f); 79static int pxe_fs_read(struct open_file *f, void *buf, size_t size, size_t *resid); 80static int pxe_fs_write(struct open_file *f, void *buf, size_t size, size_t *resid); 81static off_t pxe_fs_seek(struct open_file *f, off_t offset, int where); 82static int pxe_fs_stat(struct open_file *f, struct stat *sb); | 90extern struct netif_stats pxe_st[]; 91extern struct in_addr rootip; 92extern char rootpath[FNAME_SIZE]; |
83 | 93 |
94struct netif_dif pxe_ifs[] = { 95/* dif_unit dif_nsel dif_stats dif_private */ 96 {0, 1, &pxe_st[0], 0} 97}; |
|
84 | 98 |
99struct netif_stats pxe_st[NENTS(pxe_ifs)]; 100 101struct netif_driver pxenetif = { 102 "pxenet", 103 pxe_netif_match, 104 pxe_netif_probe, 105 pxe_netif_init, 106 pxe_netif_get, 107 pxe_netif_put, 108 pxe_netif_end, 109 pxe_ifs, 110 NENTS(pxe_ifs) 111}; 112 113struct netif_driver *netif_drivers[] = { 114 &pxenetif, 115 NULL 116}; 117 |
|
85struct devsw pxedisk = { 86 "pxe", 87 DEVT_NET, 88 pxe_init, 89 pxe_strategy, 90 pxe_open, 91 pxe_close, 92 noioctl, 93 pxe_print 94}; 95 | 118struct devsw pxedisk = { 119 "pxe", 120 DEVT_NET, 121 pxe_init, 122 pxe_strategy, 123 pxe_open, 124 pxe_close, 125 noioctl, 126 pxe_print 127}; 128 |
96struct fs_ops pxe_fsops = { 97 "pxe", 98 pxe_fs_open, 99 pxe_fs_close, 100 pxe_fs_read, 101 pxe_fs_write, 102 pxe_fs_seek, 103 pxe_fs_stat 104}; 105 | |
106/* 107 * This function is called by the loader to enable PXE support if we 108 * are booted by PXE. The passed in pointer is a pointer to the 109 * PXENV+ structure. 110 */ 111void 112pxe_enable(void *pxeinfo) 113{ 114 pxenv_p = (pxenv_t *)pxeinfo; 115} 116 117/* 118 * return true if pxe structures are found/initialized, 119 * also figures out our IP information via the pxe cached info struct 120 */ 121static int 122pxe_init(void) 123{ 124 t_PXENV_GET_CACHED_INFO *gci_p; | 129/* 130 * This function is called by the loader to enable PXE support if we 131 * are booted by PXE. The passed in pointer is a pointer to the 132 * PXENV+ structure. 133 */ 134void 135pxe_enable(void *pxeinfo) 136{ 137 pxenv_p = (pxenv_t *)pxeinfo; 138} 139 140/* 141 * return true if pxe structures are found/initialized, 142 * also figures out our IP information via the pxe cached info struct 143 */ 144static int 145pxe_init(void) 146{ 147 t_PXENV_GET_CACHED_INFO *gci_p; |
125 BOOTPLAYER *bootplayer; | |
126 int counter; 127 uint8_t checksum; 128 uint8_t *checkptr; 129 130 if(pxenv_p == NULL) 131 return (0); 132 133 /* look for "PXENV+" */ --- 29 unchanged lines hidden (view full) --- 163 bzero(gci_p, sizeof(*gci_p)); 164 gci_p->PacketType = PXENV_PACKET_TYPE_BINL_REPLY; 165 pxe_call(PXENV_GET_CACHED_INFO); 166 if (gci_p->Status != 0) { 167 pxe_perror(gci_p->Status); 168 pxenv_p = NULL; 169 return (0); 170 } | 148 int counter; 149 uint8_t checksum; 150 uint8_t *checkptr; 151 152 if(pxenv_p == NULL) 153 return (0); 154 155 /* look for "PXENV+" */ --- 29 unchanged lines hidden (view full) --- 185 bzero(gci_p, sizeof(*gci_p)); 186 gci_p->PacketType = PXENV_PACKET_TYPE_BINL_REPLY; 187 pxe_call(PXENV_GET_CACHED_INFO); 188 if (gci_p->Status != 0) { 189 pxe_perror(gci_p->Status); 190 pxenv_p = NULL; 191 return (0); 192 } |
171 bootplayer = (BOOTPLAYER *) 172 PTOV((gci_p->Buffer.segment << 4) + gci_p->Buffer.offset); 173 serverip = bootplayer->sip; 174 servername = strdup(bootplayer->Sname); 175 bootfile = strdup(bootplayer->bootfile); 176 myip = bootplayer->yip; 177 secondip = bootplayer->sip; | 193 bcopy(PTOV((gci_p->Buffer.segment << 4) + gci_p->Buffer.offset), 194 &bootplayer, gci_p->BufferSize); |
178 | 195 |
196 /* 197 * XXX - This is a major cop out. We should request this 198 * from DHCP, but we can't do that until we have full UNDI 199 * support. 200 * 201 * Also set the nfs server's IP. 202 */ 203 strcpy(rootpath, PXENFSROOTPATH); 204 rootip.s_addr = bootplayer.sip; 205 |
|
179 return (1); 180} 181 | 206 return (1); 207} 208 |
182int 183pxe_tftpopen(uint32_t srcip, uint32_t gateip, char *filename, uint16_t port, 184 uint16_t pktsize) 185{ 186 t_PXENV_TFTP_OPEN *tftpo_p; | |
187 | 209 |
188 tftpo_p = (t_PXENV_TFTP_OPEN *)scratch_buffer; 189 bzero(tftpo_p, sizeof(*tftpo_p)); 190 tftpo_p->ServerIPAddress = srcip; 191 tftpo_p->GatewayIPAddress = gateip; 192 tftpo_p->TFTPPort = port; 193 tftpo_p->PacketSize = pktsize; 194 bcopy(filename, tftpo_p->FileName, strlen(filename)); 195 pxe_call(PXENV_TFTP_OPEN); 196 pxe_return_status = tftpo_p->Status; 197 if (tftpo_p->Status != 0) 198 return (-1); 199 return (tftpo_p->PacketSize); | 210static int 211pxe_strategy(void *devdata, int flag, daddr_t dblk, size_t size, 212 void *buf, size_t *rsize) 213{ 214 return (EIO); |
200} 201 | 215} 216 |
202int 203pxe_tftpclose(void) | 217static int 218pxe_open(struct open_file *f, ...) |
204{ | 219{ |
205 t_PXENV_TFTP_CLOSE *tftpc_p; | 220 va_list args; 221 char *devname; /* Device part of file name (or NULL). */ 222 int error = 0; |
206 | 223 |
207 tftpc_p = (t_PXENV_TFTP_CLOSE *)scratch_buffer; 208 bzero(tftpc_p, sizeof(*tftpc_p)); 209 pxe_call(PXENV_TFTP_CLOSE); 210 pxe_return_status = tftpc_p->Status; 211 if (tftpc_p->Status != 0) 212 return (-1); 213 return (1); | 224 va_start(args, f); 225 devname = va_arg(args, char*); 226 va_end(args); 227 228 /* On first open, do netif open, mount, etc. */ 229 if (pxe_opens == 0) { 230 /* Find network interface. */ 231 if (pxe_sock < 0) { 232 pxe_sock = netif_open(devname); 233 if (pxe_sock < 0) { 234 printf("pxe_open: netif_open() failed\n"); 235 return (ENXIO); 236 } 237 if (debug) 238 printf("pxe_open: netif_open() succeeded\n"); 239 } 240 } 241 pxe_opens++; 242 f->f_devdata = &pxe_sock; 243 return (error); |
214} 215 | 244} 245 |
216int 217pxe_tftpread(void *buf) | 246static int 247pxe_close(struct open_file *f) |
218{ | 248{ |
219 t_PXENV_TFTP_READ *tftpr_p; | |
220 | 249 |
221 tftpr_p = (t_PXENV_TFTP_READ *)scratch_buffer; 222 bzero(tftpr_p, sizeof(*tftpr_p)); 223 224 tftpr_p->Buffer.segment = VTOPSEG(data_buffer); 225 tftpr_p->Buffer.offset = VTOPOFF(data_buffer); | 250#ifdef PXE_DEBUG 251 if (debug) 252 printf("pxe_close: opens=%d\n", pxe_opens); 253#endif |
226 | 254 |
227 pxe_call(PXENV_TFTP_READ); | 255 /* On last close, do netif close, etc. */ 256 f->f_devdata = NULL; 257 /* Extra close call? */ 258 if (pxe_opens <= 0) 259 return (0); 260 pxe_opens--; 261 /* Not last close? */ 262 if (pxe_opens > 0) 263 return(0); 264 rootip.s_addr = 0; 265 if (pxe_sock >= 0) { 266#ifdef PXE_DEBUG 267 if (debug) 268 printf("pxe_close: calling netif_close()\n"); 269#endif 270 netif_close(pxe_sock); 271 pxe_sock = -1; 272 } 273 return (0); 274} |
228 | 275 |
229 /* XXX - I don't know why we need this. */ 230 delay(1000); | 276static void 277pxe_print(int verbose) 278{ 279 if (pxenv_p != NULL) { 280 if (*bootplayer.Sname == '\0') { 281 printf(" "IP_STR":%s\n", 282 IP_ARGS(htonl(bootplayer.sip)), 283 bootplayer.bootfile); 284 } else { 285 printf(" %s:%s\n", bootplayer.Sname, 286 bootplayer.bootfile); 287 } 288 } |
231 | 289 |
232 pxe_return_status = tftpr_p->Status; 233 if (tftpr_p->Status != 0) 234 return (-1); 235 bcopy(data_buffer, buf, tftpr_p->BufferSize); 236 return (tftpr_p->BufferSize); | 290 return; |
237} 238 | 291} 292 |
293 |
|
239void 240pxe_perror(int err) 241{ 242 return; 243} 244 | 294void 295pxe_perror(int err) 296{ 297 return; 298} 299 |
245 | |
246void 247pxe_call(int func) 248{ 249 bzero(&v86, sizeof(v86)); 250 bzero(data_buffer, sizeof(data_buffer)); 251 v86.ctl = V86_ADDR | V86_CALLF | V86_FLAGS; 252 /* high 16 == segment, low 16 == offset, shift and or */ 253 v86.addr = 254 ((uint32_t)pxenv_p->RMEntry.segment << 16) | pxenv_p->RMEntry.offset; 255 v86.es = VTOPSEG(scratch_buffer); 256 v86.edi = VTOPOFF(scratch_buffer); 257 v86.ebx = func; 258 v86int(); 259 v86.ctl = V86_FLAGS; 260} 261 | 300void 301pxe_call(int func) 302{ 303 bzero(&v86, sizeof(v86)); 304 bzero(data_buffer, sizeof(data_buffer)); 305 v86.ctl = V86_ADDR | V86_CALLF | V86_FLAGS; 306 /* high 16 == segment, low 16 == offset, shift and or */ 307 v86.addr = 308 ((uint32_t)pxenv_p->RMEntry.segment << 16) | pxenv_p->RMEntry.offset; 309 v86.es = VTOPSEG(scratch_buffer); 310 v86.edi = VTOPOFF(scratch_buffer); 311 v86.ebx = func; 312 v86int(); 313 v86.ctl = V86_FLAGS; 314} 315 |
262static int 263pxe_strategy(void *devdata, int flag, daddr_t dblk, size_t size, 264 void *buf, size_t *rsize) | 316 317time_t 318getsecs() |
265{ | 319{ |
266 return (EIO); | 320 time_t n = 0; 321 time(&n); 322 return n; |
267} 268 269static int | 323} 324 325static int |
270pxe_open(struct open_file *f, ...) | 326pxe_netif_match(struct netif *nif, void *machdep_hint) |
271{ | 327{ |
272 return (0); | 328 return 1; |
273} 274 | 329} 330 |
331 |
|
275static int | 332static int |
276pxe_close(struct open_file *f) | 333pxe_netif_probe(struct netif *nif, void *machdep_hint) |
277{ | 334{ |
278 return (0); 279} | 335 t_PXENV_UDP_OPEN *udpopen_p = (t_PXENV_UDP_OPEN *)scratch_buffer; 336 bzero(udpopen_p, sizeof(*udpopen_p)); |
280 | 337 |
281static void 282pxe_print(int verbose) 283{ 284 if (pxenv_p != NULL) { 285 if (*servername == '\0') { 286 printf(" "IP_STR":/%s\n", IP_ARGS(htonl(serverip)), 287 bootfile); 288 } else { 289 printf(" %s:/%s\n", servername, bootfile); 290 } 291 } | 338 udpopen_p->src_ip = bootplayer.yip; 339 pxe_call(PXENV_UDP_OPEN); |
292 | 340 |
293 return; | 341 if (udpopen_p->status != 0) 342 printf("pxe_netif_probe: failed %x\n", udpopen_p->status); 343 return 0; |
294} 295 | 344} 345 |
296 297/* 298 * Most of this code was ripped from libstand/tftp.c and 299 * modified to work with pxe. :) 300 */ 301#define RSPACE 520 /* max data packet, rounded up */ 302 303struct tftp_handle { 304 int currblock; /* contents of lastdata */ 305 int islastblock; /* flag */ 306 int validsize; 307 int off; 308 int opened; 309 char *path; /* saved for re-requests */ 310 u_char space[RSPACE]; 311}; 312 313static int 314tftp_makereq(h) 315 struct tftp_handle *h; | 346static void 347pxe_netif_end(struct netif *nif) |
316{ | 348{ |
317 ssize_t res; 318 char *p; 319 320 p = h->path; | 349 t_PXENV_UDP_CLOSE *udpclose_p = (t_PXENV_UDP_CLOSE *)scratch_buffer; 350 bzero(udpclose_p, sizeof(*udpclose_p)); |
321 | 351 |
322 if (*p == '/') 323 ++p; 324 if (h->opened) 325 pxe_tftpclose(); 326 327 if (pxe_tftpopen(serverip, 0, p, htons(69), PXE_TFTP_BUFFER_SIZE) < 0) 328 return(ENOENT); 329 pxe_open_status = pxe_return_status; 330 res = pxe_tftpread(h->space); 331 332 if (res == -1) 333 return (errno); 334 h->currblock = 1; 335 h->validsize = res; 336 h->islastblock = 0; 337 if (res < SEGSIZE) 338 h->islastblock = 1; /* very short file */ 339 return (0); | 352 pxe_call(PXENV_UDP_CLOSE); 353 if (udpclose_p->status != 0) 354 printf("pxe_end failed %x\n", udpclose_p->status); |
340} 341 | 355} 356 |
342/* ack block, expect next */ 343static int 344tftp_getnextblock(h) 345 struct tftp_handle *h; | 357static void 358pxe_netif_init(struct iodesc *desc, void *machdep_hint) |
346{ | 359{ |
347 int res; 348 349 res = pxe_tftpread(h->space); 350 351 if (res == -1) /* 0 is OK! */ 352 return (errno); 353 354 h->currblock++; 355 h->validsize = res; 356 if (res < SEGSIZE) 357 h->islastblock = 1; /* EOF */ 358 return (0); | |
359} 360 361static int | 360} 361 362static int |
362pxe_fs_open(const char *path, struct open_file *f) | 363pxe_netif_get(struct iodesc *desc, void *pkt, size_t len, time_t timeout) |
363{ | 364{ |
364 struct tftp_handle *tftpfile; 365 int res; 366 367 /* make sure the device is a PXE device */ 368 if(f->f_dev != &pxedisk) 369 return (EINVAL); 370 371 tftpfile = (struct tftp_handle *) malloc(sizeof(*tftpfile)); 372 if (!tftpfile) 373 return (ENOMEM); 374 375 tftpfile->off = 0; 376 tftpfile->path = strdup(path); 377 if (tftpfile->path == NULL) { 378 free(tftpfile); 379 return(ENOMEM); 380 } 381 382 res = tftp_makereq(tftpfile); 383 384 if (res) { 385 free(tftpfile->path); 386 free(tftpfile); 387 return (res); 388 } 389 tftpfile->opened = 1; 390 f->f_fsdata = (void *) tftpfile; 391 return(0); | 365 return len; |
392} 393 394static int | 366} 367 368static int |
395pxe_fs_close(struct open_file *f) | 369pxe_netif_put(struct iodesc *desc, void *pkt, size_t len) |
396{ | 370{ |
397 struct tftp_handle *tftpfile; 398 tftpfile = (struct tftp_handle *) f->f_fsdata; 399 400 if (tftpfile) { 401 if (tftpfile->opened) 402 pxe_tftpclose(); 403 free(tftpfile->path); 404 free(tftpfile); 405 } 406 return (0); | 371 return len; |
407} 408 | 372} 373 |
409static int 410pxe_fs_read(struct open_file *f, void *addr, size_t size, size_t *resid) | 374ssize_t 375sendudp(struct iodesc *h, void *pkt, size_t len) |
411{ | 376{ |
412 struct tftp_handle *tftpfile; 413 static int tc = 0; 414 char *dest = (char *)addr; 415 tftpfile = (struct tftp_handle *) f->f_fsdata; | 377 t_PXENV_UDP_WRITE *udpwrite_p = (t_PXENV_UDP_WRITE *)scratch_buffer; 378 bzero(udpwrite_p, sizeof(*udpwrite_p)); 379 380 udpwrite_p->ip = bootplayer.sip; 381 udpwrite_p->dst_port = h->destport; 382 udpwrite_p->src_port = h->myport; 383 udpwrite_p->buffer_size = len; 384 udpwrite_p->buffer.segment = VTOPSEG(pkt); 385 udpwrite_p->buffer.offset = VTOPOFF(pkt); |
416 | 386 |
417 while (size > 0) { 418 int needblock, count; | 387 pxe_call(PXENV_UDP_WRITE); |
419 | 388 |
420 if (!(tc++ % 16)) 421 twiddle(); | 389 /* XXX - I dont know why we need this. */ 390 delay(1000); 391 if (udpwrite_p->status != 0) 392 printf("sendudp failed %x\n", udpwrite_p->status); |
422 | 393 |
423 needblock = tftpfile->off / SEGSIZE + 1; 424 425 if (tftpfile->currblock > needblock) /* seek backwards */ 426 tftp_makereq(tftpfile); /* no error check, it worked 427 * for open */ 428 429 while (tftpfile->currblock < needblock) { 430 int res; 431 432 res = tftp_getnextblock(tftpfile); 433 if (res) { /* no answer */ 434 return (res); 435 } 436 if (tftpfile->islastblock) 437 break; 438 } 439 440 if (tftpfile->currblock == needblock) { 441 int offinblock, inbuffer; 442 offinblock = tftpfile->off % SEGSIZE; 443 444 inbuffer = tftpfile->validsize - offinblock; 445 if (inbuffer < 0) { 446 return (EINVAL); 447 } 448 count = (size < inbuffer ? size : inbuffer); 449 bcopy(tftpfile->space + offinblock, 450 dest, count); 451 452 dest += count; 453 tftpfile->off += count; 454 size -= count; 455 456 if ((tftpfile->islastblock) && (count == inbuffer)) 457 break; /* EOF */ 458 } else { 459 printf("tftp: block %d not found\n", needblock); 460 return (EINVAL); 461 } 462 463 } 464 465 if (resid) 466 *resid = size; 467 return(0); | 394 return len; |
468} 469 | 395} 396 |
470static int 471pxe_fs_write(struct open_file *f, void *buf, size_t size, size_t *resid) | 397ssize_t 398readudp(struct iodesc *h, void *pkt, size_t len, time_t timeout) |
472{ | 399{ |
473 return 0; 474} | 400 t_PXENV_UDP_READ *udpread_p = (t_PXENV_UDP_READ *)scratch_buffer; 401 struct udphdr *uh = NULL; 402 403 uh = (struct udphdr *) pkt - 1; 404 bzero(udpread_p, sizeof(*udpread_p)); 405 406 udpread_p->dest_ip = bootplayer.yip; 407 udpread_p->d_port = h->myport; 408 udpread_p->buffer_size = len; 409 udpread_p->buffer.segment = VTOPSEG(data_buffer); 410 udpread_p->buffer.offset = VTOPOFF(data_buffer); |
475 | 411 |
476static off_t 477pxe_fs_seek(struct open_file *f, off_t offset, int where) 478{ 479 struct tftp_handle *tftpfile; 480 tftpfile = (struct tftp_handle *) f->f_fsdata; | 412 pxe_call(PXENV_UDP_READ); |
481 | 413 |
482 switch (where) { 483 case SEEK_SET: 484 tftpfile->off = offset; 485 break; 486 case SEEK_CUR: 487 tftpfile->off += offset; 488 break; 489 default: 490 errno = EOFFSET; 491 return (-1); 492 } 493 return (tftpfile->off); | 414 /* XXX - I dont know why we need this. */ 415 delay(1000); 416 if (udpread_p->status > 1) 417 printf("readudp failed %x\n", udpread_p->status); 418 bcopy(data_buffer, pkt, udpread_p->buffer_size); 419 uh->uh_sport = udpread_p->s_port; 420 return udpread_p->buffer_size; |
494} | 421} |
495 496static int 497pxe_fs_stat(struct open_file *f, struct stat *sb) 498{ 499 if (pxe_open_status != 0) 500 return -1; 501 502 sb->st_mode = 0444 | S_IFREG; 503 sb->st_nlink = 1; 504 sb->st_uid = 0; 505 sb->st_gid = 0; 506 sb->st_size = -1; 507 508 return 0; 509} | |