This source file includes following definitions.
- pxesendudp
- pxereadudp
- pxe_netif_open
- pxe_netif_close
- pxe_netif_shutdown
- pxesocktodesc
- pxeprobe
- pxe_init
- pxeinfo
- pxe_shutdown
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77 #include <sys/param.h>
78 #include <sys/socket.h>
79
80 #ifdef _STANDALONE
81 #include <lib/libkern/libkern.h>
82 #else
83 #include <string.h>
84 #endif
85
86 #include <net/if.h>
87
88 #include <netinet/in.h>
89 #include <netinet/if_ether.h>
90 #include <netinet/in_systm.h>
91 #include <netinet/ip.h>
92 #include <netinet/ip_var.h>
93 #include <netinet/udp.h>
94 #include <netinet/udp_var.h>
95
96 #include <lib/libsa/stand.h>
97 #include <lib/libsa/net.h>
98 #include <lib/libsa/bootp.h>
99
100 #include <stand/boot/bootarg.h>
101 #include <machine/biosvar.h>
102
103 #include "pxeboot.h"
104 #include "pxe.h"
105 #include "pxe_netif.h"
106
107 void (*pxe_call)(u_int16_t);
108
109 void pxecall_bangpxe(u_int16_t);
110 void pxecall_pxenv(u_int16_t);
111
112 char pxe_command_buf[256];
113
114 BOOTPLAYER bootplayer;
115
116 struct in_addr servip;
117
118 extern char *bootmac;
119
120
121
122
123
124
125
126
127 ssize_t
128 pxesendudp(struct iodesc *d, void *pkt, size_t len)
129 {
130 t_PXENV_UDP_WRITE *uw = (void *) pxe_command_buf;
131
132 uw->status = 0;
133
134 uw->ip = d->destip.s_addr;
135 uw->gw = gateip.s_addr;
136 uw->src_port = d->myport;
137 uw->dst_port = d->destport;
138 uw->buffer_size = len;
139 uw->buffer.segment = VTOPSEG(pkt);
140 uw->buffer.offset = VTOPOFF(pkt);
141
142 pxe_call(PXENV_UDP_WRITE);
143
144 if (uw->status != PXENV_STATUS_SUCCESS) {
145
146 if (uw->status != PXENV_STATUS_FAILURE)
147 printf("sendudp: PXENV_UDP_WRITE failed: 0x%x\n",
148 uw->status);
149 return -1;
150 }
151
152 return len;
153 }
154
155
156
157
158
159 ssize_t
160 pxereadudp(struct iodesc *d, void *pkt, size_t len, time_t tleft)
161 {
162 t_PXENV_UDP_READ *ur = (void *) pxe_command_buf;
163 struct udphdr *uh;
164 struct ip *ip;
165
166 uh = (struct udphdr *)pkt - 1;
167 ip = (struct ip *)uh - 1;
168
169 bzero(ur, sizeof(*ur));
170
171 ur->dest_ip = d->myip.s_addr;
172 ur->d_port = d->myport;
173 ur->buffer_size = len;
174 ur->buffer.segment = VTOPSEG(pkt);
175 ur->buffer.offset = VTOPOFF(pkt);
176
177
178
179 pxe_call(PXENV_UDP_READ);
180
181 if (ur->status != PXENV_STATUS_SUCCESS) {
182
183 if (ur->status != PXENV_STATUS_FAILURE)
184 printf("readudp: PXENV_UDP_READ_failed: 0x%0x\n",
185 ur->status);
186 return -1;
187 }
188
189 ip->ip_src.s_addr = ur->src_ip;
190 uh->uh_sport = ur->s_port;
191 uh->uh_dport = d->myport;
192
193 return ur->buffer_size;
194 }
195
196
197
198
199
200
201
202
203
204 static int pxe_inited;
205 static struct iodesc desc;
206
207 int
208 pxe_netif_open()
209 {
210 t_PXENV_UDP_OPEN *uo = (void *) pxe_command_buf;
211
212 #ifdef NETIF_DEBUG
213 printf("pxe_netif_open()\n");
214 #endif
215 if (!pxe_inited) {
216 if (pxe_init(0) != 0)
217 return -1;
218 pxe_inited = 1;
219 }
220
221
222 bzero(uo, sizeof(*uo));
223
224 uo->src_ip = bootplayer.yip;
225
226 pxe_call(PXENV_UDP_OPEN);
227
228 if (uo->status != PXENV_STATUS_SUCCESS) {
229 printf("\npxe_netif_open: PXENV_UDP_OPEN failed: 0x%x\n",
230 uo->status);
231 return -1;
232 }
233
234 bcopy(bootplayer.CAddr, desc.myea, ETHER_ADDR_LEN);
235 bootmac = bootplayer.CAddr;
236
237
238
239
240
241 desc.xid = bootplayer.ident;
242
243 return 0;
244 }
245
246 void
247 pxe_netif_close(sock)
248 int sock;
249 {
250 t_PXENV_UDP_CLOSE *uc = (void *) pxe_command_buf;
251
252 #ifdef NETIF_DEBUG
253 if (sock != 0)
254 printf("pxe_netif_close: sock=%d\n", sock);
255 #endif
256
257 uc->status = 0;
258
259 pxe_call(PXENV_UDP_CLOSE);
260
261 if (uc->status != PXENV_STATUS_SUCCESS)
262 printf("pxe_netif_end: PXENV_UDP_CLOSE failed: 0x%x\n",
263 uc->status);
264 }
265
266 void
267 pxe_netif_shutdown()
268 {
269 #ifdef NETIF_DEBUG
270 printf("pxe_netif_shutdown()\n");
271 #endif
272
273 pxe_shutdown();
274 }
275
276 struct iodesc *
277 pxesocktodesc(sock)
278 int sock;
279 {
280
281 #ifdef NETIF_DEBUG
282 if (sock != 0)
283 return 0;
284 else
285 #endif
286 return &desc;
287 }
288
289
290
291
292
293 u_int16_t pxe_command_buf_seg;
294 u_int16_t pxe_command_buf_off;
295
296 extern u_int16_t bangpxe_off, bangpxe_seg;
297 extern u_int16_t pxenv_off, pxenv_seg;
298
299
300
301 void
302 pxeprobe(void)
303 {
304 if (!pxe_inited) {
305 if (pxe_init(1) == 0) {
306 pxe_inited = 1;
307 }
308 }
309 }
310
311 int
312 pxe_init(int quiet)
313 {
314 t_PXENV_GET_CACHED_INFO *gci = (void *) pxe_command_buf;
315 pxenv_t *pxenv;
316 pxe_t *pxe;
317 char *cp;
318 int i;
319 u_int8_t cksum, *ucp;
320
321
322
323
324
325
326
327
328
329
330
331
332
333 pxenv = NULL;
334 pxe = NULL;
335
336 for (cp = (char *)0xa0000; cp > (char *)0x10000; cp -= 2) {
337 if (pxenv == NULL) {
338 pxenv = (pxenv_t *)cp;
339 if (memcmp(pxenv->Signature, S_SIZE("PXENV+")) != 0)
340 pxenv = NULL;
341 else {
342 for (i = 0, ucp = (u_int8_t *)cp, cksum = 0;
343 i < pxenv->Length; i++)
344 cksum += ucp[i];
345 if (cksum != 0) {
346 printf("\npxe_init: bad cksum (0x%x) "
347 "for PXENV+ at 0x%lx\n", cksum,
348 (u_long) cp);
349 pxenv = NULL;
350 }
351 }
352 }
353
354 if (pxe == NULL) {
355 pxe = (pxe_t *)cp;
356 if (memcmp(pxe->Signature, S_SIZE("!PXE")) != 0)
357 pxe = NULL;
358 else {
359 for (i = 0, ucp = (u_int8_t *)cp, cksum = 0;
360 i < pxe->StructLength; i++)
361 cksum += ucp[i];
362 if (cksum != 0) {
363 printf("pxe_init: bad cksum (0x%x) "
364 "for !PXE at 0x%lx\n", cksum,
365 (u_long) cp);
366 pxe = NULL;
367 }
368 }
369 }
370
371 if (pxe != NULL && pxenv != NULL)
372 break;
373 }
374
375 if (pxe == NULL && pxenv == NULL) {
376 if (!quiet) printf("pxe_init: No PXE BIOS found.\n");
377 return 1;
378 }
379
380 if (pxenv == NULL) {
381
382
383 printf(quiet ? " pxe!" : "PXE present\n");
384 } else {
385 int bang = 0;
386
387 if (pxenv->Version >= 0x0201 && pxe != NULL) {
388
389 bang = 1;
390 }
391
392 if (quiet) {
393 printf(" pxe%c[%d.%d]",
394 (bang ? '!' : '+'),
395 (pxenv->Version >> 8) & 0xff,
396 pxenv->Version & 0xff);
397 } else {
398 printf("PXE BIOS Version %d.%d\n",
399 (pxenv->Version >> 8) & 0xff,
400 pxenv->Version & 0xff);
401 }
402
403 if (bang) {
404 pxenv = NULL;
405 }
406 }
407
408 if (pxenv == NULL) {
409 pxe_call = pxecall_bangpxe;
410 bangpxe_off = pxe->EntryPointSP.offset;
411 bangpxe_seg = pxe->EntryPointSP.segment;
412 } else {
413 pxe_call = pxecall_pxenv;
414 pxenv_off = pxenv->RMEntry.offset;
415 pxenv_seg = pxenv->RMEntry.segment;
416 }
417
418
419
420
421
422 pxe_command_buf_seg = VTOPSEG(pxe_command_buf);
423 pxe_command_buf_off = VTOPOFF(pxe_command_buf);
424
425
426
427
428 bzero(gci, sizeof(*gci));
429 gci->PacketType = PXENV_PACKET_TYPE_CACHED_REPLY;
430 pxe_call(PXENV_GET_CACHED_INFO);
431
432 if (gci->Status != PXENV_STATUS_SUCCESS) {
433 printf("\npxeinfo: PXENV_GET_CACHED_INFO failed: 0x%x\n",
434 gci->Status);
435 return 1;
436 }
437
438 memcpy(&bootplayer,
439 SEGOFF2FLAT(gci->Buffer.segment, gci->Buffer.offset),
440 gci->BufferSize);
441
442 bcopy(&bootplayer.yip, &myip.s_addr, sizeof(myip.s_addr));
443 bcopy(&bootplayer.sip, &servip.s_addr, sizeof(servip.s_addr));
444
445
446 if (IN_CLASSA(myip.s_addr))
447 netmask = IN_CLASSA_NET;
448 else if (IN_CLASSB(myip.s_addr))
449 netmask = IN_CLASSB_NET;
450 else
451 netmask = IN_CLASSC_NET;
452
453 return 0;
454 }
455
456 void
457 pxeinfo(void)
458 {
459 u_int8_t *p;
460 #ifdef PXE_DEBUG
461 t_PXENV_UNDI_GET_NIC_TYPE *gnt = (void *) pxe_command_buf;
462 #endif
463
464 printf(" mac %s", ether_sprintf(bootplayer.CAddr));
465 p = (u_int8_t *)&myip.s_addr;
466 printf(", ip %d.%d.%d.%d", p[0], p[1], p[2], p[3]);
467 p = (u_int8_t *)&servip.s_addr;
468 printf(", server %d.%d.%d.%d", p[0], p[1], p[2], p[3]);
469
470 #ifdef PXE_DEBUG
471
472
473
474 bzero(gnt, sizeof(*gnt));
475 pxe_call(PXENV_UNDI_GET_NIC_TYPE);
476
477 if (gnt->Status != PXENV_STATUS_SUCCESS) {
478 printf("\npxeinfo: PXENV_UNDI_GET_NIC_TYPE failed: 0x%x\n",
479 gnt->Status);
480 return;
481 }
482
483 switch (gnt->NicType) {
484 case PCI_NIC:
485 case CardBus_NIC:
486
487
488
489
490 printf("\nPXE: Using %s device at bus %d device %d function %d\n",
491 gnt->NicType == PCI_NIC ? "PCI" : "CardBus",
492 (gnt->info.pci.BusDevFunc >> 8) & 0xff,
493 (gnt->info.pci.BusDevFunc >> 3) & 0x1f,
494 gnt->info.pci.BusDevFunc & 0x7);
495 break;
496
497 case PnP_NIC:
498
499 printf("\nPXE: Using PnP device at 0x%x\n",
500 gnt->info.pnp.CardSelNum);
501 }
502 #endif
503 }
504
505 void
506 pxe_shutdown(void)
507 {
508 int try;
509 t_PXENV_UNLOAD_STACK *unload = (void *) pxe_command_buf;
510 t_PXENV_UNDI_SHUTDOWN *shutdown = (void *) pxe_command_buf;
511 #ifdef PXE_DEBUG
512 t_PXENV_UDP_CLOSE *close = (void *) pxe_command_buf;
513 #endif
514
515 if (pxe_call == NULL)
516 return;
517
518
519 pxe_call(PXENV_UDP_CLOSE);
520 #ifdef PXE_DEBUG
521 printf("pxe_shutdown: PXENV_UDP_CLOSE returned 0x%x\n", close->status);
522 #endif
523
524
525 for (try = 3; try > 0; try--) {
526 pxe_call(PXENV_UNDI_SHUTDOWN);
527
528 if (shutdown->Status == PXENV_STATUS_SUCCESS)
529 break;
530
531 printf("pxe_shutdown: PXENV_UNDI_SHUTDOWN failed: 0x%x\n",
532 shutdown->Status);
533
534 if (try != 1)
535 sleep(1);
536 }
537
538
539 for (try = 3; try > 0; try--) {
540 pxe_call(PXENV_UNLOAD_STACK);
541
542 if (unload->Status == PXENV_STATUS_SUCCESS)
543 break;
544
545 printf("pxe_shutdown: PXENV_UNLOAD_STACK failed: 0x%x\n",
546 unload->Status);
547
548 if (try != 1)
549 sleep(1);
550 }
551 }