Deleted Added
full compact
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}