Remove *_fill_nic() calls, and directly set nic->ioaddr and nic->irqno .
[gpxe.git] / contrib / baremetal / main.c
blob7b0de44c1ba7388ea6e139baed1474a0b6102a3c
1 /**************************************************************************
2 ETHERBOOT - BOOTP/TFTP Bootstrap Program
4 Author: Martin Renters
5 Date: Dec/93
7 Literature dealing with the network protocols:
8 ARP - RFC826
9 RARP - RFC903
10 UDP - RFC768
11 BOOTP - RFC951, RFC2132 (vendor extensions)
12 DHCP - RFC2131, RFC2132 (options)
13 TFTP - RFC1350, RFC2347 (options), RFC2348 (blocksize), RFC2349 (tsize)
14 RPC - RFC1831, RFC1832 (XDR), RFC1833 (rpcbind/portmapper)
15 NFS - RFC1094, RFC1813 (v3, useful for clarifications, not implemented)
17 **************************************************************************/
19 /* #define MDEBUG */
21 #include "etherboot.h"
22 #include "nic.h"
24 int jmp_bootmenu[10];
26 struct arptable_t arptable[MAX_ARP];
28 const char *kernel;
29 char kernel_buf[128];
30 struct rom_info rom;
32 #ifdef IMAGE_MENU
33 static char *imagelist[RFC1533_VENDOR_NUMOFIMG];
34 static int useimagemenu;
35 int menutmo,menudefault;
36 unsigned char *defparams = NULL;
37 int defparams_max = 0;
38 #endif
39 #ifdef MOTD
40 char *motd[RFC1533_VENDOR_NUMOFMOTD];
41 #endif
42 #ifdef IMAGE_FREEBSD
43 int freebsd_howto = 0;
44 #endif
45 int vendorext_isvalid;
46 char config_buffer[TFTP_MAX_PACKET+1]; /* +1 for null byte */
47 unsigned long netmask;
48 char *hostname = "";
49 int hostnamelen = 0;
50 #if defined(ETHERBOOT16) || defined(INTERNAL_BOOTP_DATA)
51 struct bootpd_t bootp_data;
52 #endif
53 unsigned long xid;
54 unsigned char *end_of_rfc1533 = NULL;
55 #ifndef NO_DHCP_SUPPORT
56 int dhcp_reply;
57 in_addr dhcp_server = { 0L };
58 in_addr dhcp_addr = { 0L };
59 #endif /* NO_DHCP_SUPPORT */
61 unsigned char vendorext_magic[] = {0xE4,0x45,0x74,0x68}; /* äEth */
62 #ifdef NO_DHCP_SUPPORT
63 char rfc1533_cookie[5] = { RFC1533_COOKIE, RFC1533_END };
64 #else
65 char rfc1533_cookie[] = { RFC1533_COOKIE};
66 char rfc1533_end[]={RFC1533_END };
67 static const char dhcpdiscover[]={
68 RFC2132_MSG_TYPE,1,DHCPDISCOVER,
69 RFC2132_MAX_SIZE,2, /* request as much as we can */
70 sizeof(struct bootpd_t) / 256, sizeof(struct bootpd_t) % 256,
71 RFC2132_PARAM_LIST,4,RFC1533_NETMASK,RFC1533_GATEWAY,
72 RFC1533_HOSTNAME
74 static const char dhcprequest []={
75 RFC2132_MSG_TYPE,1,DHCPREQUEST,
76 RFC2132_SRV_ID,4,0,0,0,0,
77 RFC2132_REQ_ADDR,4,0,0,0,0,
78 RFC2132_MAX_SIZE,2, /* request as much as we can */
79 sizeof(struct bootpd_t) / 256, sizeof(struct bootpd_t) % 256,
80 /* request parameters */
81 RFC2132_PARAM_LIST,
82 #ifdef IMAGE_FREEBSD
83 /* 4 standard + 6 vendortags + 8 motd + 16 menu items */
84 4 + 6 + 8 + 16,
85 #else
86 /* 4 standard + 5 vendortags + 8 motd + 16 menu items */
87 4 + 5 + 8 + 16,
88 #endif
89 /* Standard parameters */
90 RFC1533_NETMASK, RFC1533_GATEWAY,
91 RFC1533_HOSTNAME,
92 RFC1533_ROOTPATH, /* only passed to the booted image */
93 /* Etherboot vendortags */
94 RFC1533_VENDOR_MAGIC,
95 RFC1533_VENDOR_ADDPARM,
96 RFC1533_VENDOR_ETHDEV,
97 #ifdef IMAGE_FREEBSD
98 RFC1533_VENDOR_HOWTO,
99 #endif
100 RFC1533_VENDOR_MNUOPTS, RFC1533_VENDOR_SELECTION,
101 /* 8 MOTD entries */
102 RFC1533_VENDOR_MOTD,
103 RFC1533_VENDOR_MOTD+1,
104 RFC1533_VENDOR_MOTD+2,
105 RFC1533_VENDOR_MOTD+3,
106 RFC1533_VENDOR_MOTD+4,
107 RFC1533_VENDOR_MOTD+5,
108 RFC1533_VENDOR_MOTD+6,
109 RFC1533_VENDOR_MOTD+7,
110 /* 16 image entries */
111 RFC1533_VENDOR_IMG,
112 RFC1533_VENDOR_IMG+1,
113 RFC1533_VENDOR_IMG+2,
114 RFC1533_VENDOR_IMG+3,
115 RFC1533_VENDOR_IMG+4,
116 RFC1533_VENDOR_IMG+5,
117 RFC1533_VENDOR_IMG+6,
118 RFC1533_VENDOR_IMG+7,
119 RFC1533_VENDOR_IMG+8,
120 RFC1533_VENDOR_IMG+9,
121 RFC1533_VENDOR_IMG+10,
122 RFC1533_VENDOR_IMG+11,
123 RFC1533_VENDOR_IMG+12,
124 RFC1533_VENDOR_IMG+13,
125 RFC1533_VENDOR_IMG+14,
126 RFC1533_VENDOR_IMG+15,
129 #endif /* NO_DHCP_SUPPORT */
130 static const char broadcast[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
132 /**************************************************************************
133 MAIN - Kick off routine
134 **************************************************************************/
135 int main(void)
137 char *p;
138 static int card_retries = 0;
139 int i;
141 for (p=_edata; p<_end; p++)
142 *p = 0; /* Zero BSS */
144 #ifdef CONSOLE_SERIAL
145 (void)serial_init();
146 #endif
148 #ifdef DELIMITERLINES
149 for (i=0; i<80; i++) putchar('=');
150 #endif
152 #ifdef ETHERBOOT32
153 rom = *(struct rom_info *)ROM_INFO_LOCATION;
154 printf("ROM segment %#x length %#x reloc %#x\n", rom.rom_segment,
155 rom.rom_length << 1, ((unsigned long)_start) >> 4);
156 #endif
157 #ifdef ETHERBOOT16
158 fmemcpy(&rom, (Address)ROM_INFO_LOCATION, sizeof(rom));
159 printf("ROM segment %#x length %#x\n", rom.rom_segment,
160 rom.rom_length << 1);
161 #endif
162 #ifdef ASK_BOOT
163 while (1) {
164 int c;
165 unsigned long time;
166 printf(ASK_PROMPT);
167 #if ASK_BOOT > 0
168 for (time = currticks() + ASK_BOOT*TICKS_PER_SEC; !iskey(); )
169 if (currticks() > time) {
170 c = ANS_DEFAULT;
171 goto done;
173 #endif
174 c = getchar();
175 if ((c >= 'a') && (c <= 'z')) c &= 0x5F;
176 if (c == '\n') c = ANS_DEFAULT;
177 done:
178 if ((c >= ' ') && (c <= '~')) putchar(c);
179 putchar('\n');
180 if (c == ANS_LOCAL)
181 exit(0);
182 if (c == ANS_NETWORK)
183 break;
185 #endif
186 #if (TRY_FLOPPY_FIRST > 0) && defined(FLOPPY)
187 disk_init();
188 printf("Trying floppy");
189 for (i = TRY_FLOPPY_FIRST; i-- > 0; ) {
190 putchar('.');
191 if (disk_read(0, 0, 0, 0, ((char *) FLOPPY_BOOT_LOCATION)) != 0x8000) {
192 printf("using floppy\n");
193 exit(0);
196 printf("no floppy\n");
197 #endif /* TRY_FLOPPY_FIRST && FLOPPY */
198 print_config();
199 gateA20_set();
200 #ifdef EMERGENCYDISKBOOT
201 if (!eth_probe()) {
202 printf("No adapter found\n");
203 exit(0);
205 #else
206 while (!eth_probe()) {
207 printf("No adapter found");
208 if (!setjmp(jmp_bootmenu))
209 rfc951_sleep(++card_retries);
211 #endif
212 kernel = DEFAULT_BOOTFILE;
213 while (1) {
214 if ((i = setjmp(jmp_bootmenu)) != 0) {
215 #if defined(ANSIESC) && defined(CONSOLE_CRT)
216 ansi_reset();
217 #endif
218 bootmenu(--i);
219 } else {
220 load();
222 #if defined(ANSIESC) && defined(CONSOLE_CRT)
223 ansi_reset();
224 #endif
228 /**************************************************************************
229 LOADKERNEL - Try to load kernel image
230 **************************************************************************/
231 #ifndef FLOPPY
232 #define loadkernel(s) download((s),downloadkernel)
233 #else
234 static int loadkernel(const char *fname)
236 if (!memcmp(fname,"/dev/",5) && fname[6] == 'd') {
237 int dev, part = 0;
238 if (fname[5] == 'f') {
239 if ((dev = fname[7] - '0') < 0 || dev > 3)
240 goto nodisk; }
241 else if (fname[5] == 'h' || fname[5] == 's') {
242 if ((dev = 0x80 + fname[7] - 'a') < 0x80 || dev > 0x83)
243 goto nodisk;
244 if (fname[8]) {
245 part = fname[8] - '0';
246 if (fname[9])
247 part = 10*part + fname[9] - '0'; }
248 /* bootdisk cannot cope with more than eight partitions */
249 if (part < 0 || part > 8)
250 goto nodisk; }
251 else
252 goto nodisk;
253 return(bootdisk(dev,part)); }
254 nodisk:
255 return download(fname, downloadkernel);
257 #endif
259 /**************************************************************************
260 LOAD - Try to get booted
261 **************************************************************************/
262 void load()
264 static int bootp_completed = 0;
266 /* Find a server to get BOOTP reply from */
267 if (!bootp_completed ||
268 !arptable[ARP_CLIENT].ipaddr.s_addr || !arptable[ARP_SERVER].ipaddr.s_addr) {
269 retry:
270 bootp_completed = 0;
271 #ifdef RARP_NOT_BOOTP
272 printf("Searching for server (RARP)...\n");
273 #else
274 #ifndef NO_DHCP_SUPPORT
275 printf("Searching for server (DHCP)...\n");
276 #else
277 printf("Searching for server (BOOTP)...\n");
278 #endif
279 #endif
281 #ifdef RARP_NOT_BOOTP
282 if (!rarp()) {
283 #else
284 if (!bootp()) {
285 #endif
286 printf("No Server found\n");
287 #ifdef EMERGENCYDISKBOOT
288 exit(0);
289 #else
290 goto retry;
291 #endif
293 bootp_completed++;
295 printf("Me: %I, Server: %I",
296 arptable[ARP_CLIENT].ipaddr.s_addr,
297 arptable[ARP_SERVER].ipaddr.s_addr);
298 if (BOOTP_DATA_ADDR->bootp_reply.bp_giaddr.s_addr)
299 printf(", Relay: %I",
300 BOOTP_DATA_ADDR->bootp_reply.bp_giaddr.s_addr);
301 if (arptable[ARP_GATEWAY].ipaddr.s_addr)
302 printf(", Gateway %I", arptable[ARP_GATEWAY].ipaddr.s_addr);
303 putchar('\n');
305 #ifdef MDEBUG
306 printf("\n=>>"); getchar();
307 #endif
309 #ifdef MOTD
310 if (vendorext_isvalid)
311 show_motd();
312 #endif
313 /* Now use TFTP to load file */
314 #ifdef IMAGE_MENU
315 if (vendorext_isvalid && useimagemenu) {
316 selectImage(imagelist);
317 bootp_completed = 0;
319 #endif
320 #ifdef DOWNLOAD_PROTO_NFS
321 rpc_init();
322 #endif
323 for (;;) {
324 printf("Loading %s ",kernel);
325 while (!loadkernel(kernel)) {
326 printf("Unable to load file.\n");
327 sleep(2); /* lay off server for a while */
332 /**************************************************************************
333 DEFAULT_NETMASK - Return default netmask for IP address
334 **************************************************************************/
335 static inline unsigned long default_netmask(void)
337 int net = ntohl(arptable[ARP_CLIENT].ipaddr.s_addr) >> 24;
338 if (net <= 127)
339 return(htonl(0xff000000));
340 else if (net < 192)
341 return(htonl(0xffff0000));
342 else
343 return(htonl(0xffffff00));
346 /**************************************************************************
347 UDP_TRANSMIT - Send a UDP datagram
348 **************************************************************************/
349 int udp_transmit(unsigned long destip, unsigned int srcsock,
350 unsigned int destsock, int len, const void *buf)
352 struct iphdr *ip;
353 struct udphdr *udp;
354 struct arprequest arpreq;
355 int arpentry, i;
356 int retry;
358 ip = (struct iphdr *)buf;
359 udp = (struct udphdr *)((long)buf + sizeof(struct iphdr));
360 ip->verhdrlen = 0x45;
361 ip->service = 0;
362 ip->len = htons(len);
363 ip->ident = 0;
364 ip->frags = 0;
365 ip->ttl = 60;
366 ip->protocol = IP_UDP;
367 ip->chksum = 0;
368 ip->src.s_addr = arptable[ARP_CLIENT].ipaddr.s_addr;
369 ip->dest.s_addr = destip;
370 ip->chksum = ipchksum((unsigned short *)buf, sizeof(struct iphdr));
371 udp->src = htons(srcsock);
372 udp->dest = htons(destsock);
373 udp->len = htons(len - sizeof(struct iphdr));
374 udp->chksum = 0;
375 if (destip == IP_BROADCAST) {
376 eth_transmit(broadcast, IP, len, buf);
377 } else {
378 if (((destip & netmask) !=
379 (arptable[ARP_CLIENT].ipaddr.s_addr & netmask)) &&
380 arptable[ARP_GATEWAY].ipaddr.s_addr)
381 destip = arptable[ARP_GATEWAY].ipaddr.s_addr;
382 for(arpentry = 0; arpentry<MAX_ARP; arpentry++)
383 if (arptable[arpentry].ipaddr.s_addr == destip) break;
384 if (arpentry == MAX_ARP) {
385 printf("%I is not in my arp table!\n", destip);
386 return(0);
388 for (i = 0; i<ETHER_ADDR_SIZE; i++)
389 if (arptable[arpentry].node[i]) break;
390 if (i == ETHER_ADDR_SIZE) { /* Need to do arp request */
391 arpreq.hwtype = htons(1);
392 arpreq.protocol = htons(IP);
393 arpreq.hwlen = ETHER_ADDR_SIZE;
394 arpreq.protolen = 4;
395 arpreq.opcode = htons(ARP_REQUEST);
396 memcpy(arpreq.shwaddr, arptable[ARP_CLIENT].node, ETHER_ADDR_SIZE);
397 memcpy(arpreq.sipaddr, &arptable[ARP_CLIENT].ipaddr, sizeof(in_addr));
398 memset(arpreq.thwaddr, 0, ETHER_ADDR_SIZE);
399 memcpy(arpreq.tipaddr, &destip, sizeof(in_addr));
400 for (retry = 1; retry <= MAX_ARP_RETRIES; retry++) {
401 eth_transmit(broadcast, ARP, sizeof(arpreq),
402 &arpreq);
403 if (await_reply(AWAIT_ARP, arpentry,
404 arpreq.tipaddr, TIMEOUT)) goto xmit;
405 rfc951_sleep(retry);
406 /* We have slept for a while - the packet may
407 * have arrived by now. If not, we have at
408 * least some room in the Rx buffer for the
409 * next reply. */
410 if (await_reply(AWAIT_ARP, arpentry,
411 arpreq.tipaddr, 0)) goto xmit;
413 return(0);
415 xmit:
416 eth_transmit(arptable[arpentry].node, IP, len, buf);
418 return(1);
421 /**************************************************************************
422 DOWNLOADKERNEL - Try to load file
423 **************************************************************************/
424 int downloadkernel(data, block, len, eof)
425 unsigned char *data;
426 int block, len, eof;
428 #ifdef SIZEINDICATOR
429 static int rlen = 0;
431 if (!(block % 4) || eof) {
432 int size;
433 size = ((block-1) * rlen + len) / 1024;
435 putchar('\b');
436 putchar('\b');
437 putchar('\b');
438 putchar('\b');
440 putchar('0' + (size/1000)%10);
441 putchar('0' + (size/100)%10);
442 putchar('0' + (size/10)%10);
443 putchar('0' + (size/1)%10);
445 #endif
446 if (block == 1)
448 #ifdef SIZEINDICATOR
449 rlen=len;
450 #endif
451 if (!eof && (
452 #ifdef TAGGED_IMAGE
453 *((unsigned long *)data) == 0x1B031336L ||
454 #endif
455 #ifdef ELF_IMAGE
456 *((unsigned long *)data) == 0x464C457FL ||
457 #endif
458 #ifdef AOUT_IMAGE
459 *((unsigned short *)data) == 0x010BL ||
460 #endif
461 ((unsigned short *)data)[255] == 0xAA55))
465 else if (eof)
467 memcpy(config_buffer, data, len);
468 config_buffer[len] = 0;
469 return (1); /* done */
471 else
473 printf("error: not a tagged image\n");
474 return(0); /* error */
477 if (len != 0) {
478 if (!os_download(block, data, len))
479 return(0); /* error */
481 if (eof) {
482 os_download(block+1, data, 0); /* does not return */
483 return(0); /* error */
485 return(-1); /* there is more data */
488 #ifdef DOWNLOAD_PROTO_TFTP
489 /**************************************************************************
490 TFTP - Download extended BOOTP data, or kernel image
491 **************************************************************************/
492 int tftp(const char *name, int (*fnc)(unsigned char *, int, int, int))
494 int retry = 0;
495 static unsigned short iport = 2000;
496 unsigned short oport;
497 unsigned short len, block = 0, prevblock = 0;
498 int bcounter = 0;
499 struct tftp_t *tr;
500 struct tftp_t tp;
501 int rc;
502 int packetsize = TFTP_DEFAULTSIZE_PACKET;
504 /* Clear out the Rx queue first. It contains nothing of interest,
505 * except possibly ARP requests from the DHCP/TFTP server. We use
506 * polling throughout Etherboot, so some time may have passed since we
507 * last polled the receive queue, which may now be filled with
508 * broadcast packets. This will cause the reply to the packets we are
509 * about to send to be lost immediately. Not very clever. */
510 await_reply(AWAIT_QDRAIN, 0, NULL, 0);
512 tp.opcode = htons(TFTP_RRQ);
513 len = (sprintf((char *)tp.u.rrq, "%s%coctet%cblksize%c%d",
514 name, 0, 0, 0, TFTP_MAX_PACKET) - ((char *)&tp)) + 1;
515 if (!udp_transmit(arptable[ARP_SERVER].ipaddr.s_addr, ++iport,
516 TFTP_PORT, len, &tp))
517 return (0);
518 for (;;)
520 #ifdef CONGESTED
521 if (!await_reply(AWAIT_TFTP, iport, NULL, (block ? TFTP_REXMT : TIMEOUT)))
522 #else
523 if (!await_reply(AWAIT_TFTP, iport, NULL, TIMEOUT))
524 #endif
526 if (!block && retry++ < MAX_TFTP_RETRIES)
527 { /* maybe initial request was lost */
528 rfc951_sleep(retry);
529 if (!udp_transmit(arptable[ARP_SERVER].ipaddr.s_addr,
530 ++iport, TFTP_PORT, len, &tp))
531 return (0);
532 continue;
534 #ifdef CONGESTED
535 if (block && ((retry += TFTP_REXMT) < TFTP_TIMEOUT))
536 { /* we resend our last ack */
537 #ifdef MDEBUG
538 printf("<REXMT>\n");
539 #endif
540 udp_transmit(arptable[ARP_SERVER].ipaddr.s_addr,
541 iport, oport,
542 TFTP_MIN_PACKET, &tp);
543 continue;
545 #endif
546 break; /* timeout */
548 tr = (struct tftp_t *)&nic.packet[ETHER_HDR_SIZE];
549 if (tr->opcode == ntohs(TFTP_ERROR))
551 printf("TFTP error %d (%s)\n",
552 ntohs(tr->u.err.errcode),
553 tr->u.err.errmsg);
554 break;
557 if (tr->opcode == ntohs(TFTP_OACK)) {
558 char *p = tr->u.oack.data, *e;
560 if (prevblock) /* shouldn't happen */
561 continue; /* ignore it */
562 len = ntohs(tr->udp.len) - sizeof(struct udphdr) - 2;
563 if (len > TFTP_MAX_PACKET)
564 goto noak;
565 e = p + len;
566 while (*p != '\000' && p < e) {
567 if (!strcasecmp("blksize", p)) {
568 p += 8;
569 if ((packetsize = getdec(&p)) <
570 TFTP_DEFAULTSIZE_PACKET)
571 goto noak;
572 while (p < e && *p) p++;
573 if (p < e)
574 p++;
576 else {
577 noak:
578 tp.opcode = htons(TFTP_ERROR);
579 tp.u.err.errcode = 8;
580 len = (sprintf((char *)tp.u.err.errmsg,
581 "RFC1782 error")
582 - ((char *)&tp)) + 1;
583 udp_transmit(arptable[ARP_SERVER].ipaddr.s_addr,
584 iport, ntohs(tr->udp.src),
585 len, &tp);
586 return (0);
589 if (p > e)
590 goto noak;
591 block = tp.u.ack.block = 0; /* this ensures, that */
592 /* the packet does not get */
593 /* processed as data! */
595 else if (tr->opcode == ntohs(TFTP_DATA)) {
596 len = ntohs(tr->udp.len) - sizeof(struct udphdr) - 4;
597 if (len > packetsize) /* shouldn't happen */
598 continue; /* ignore it */
599 block = ntohs(tp.u.ack.block = tr->u.data.block); }
600 else /* neither TFTP_OACK nor TFTP_DATA */
601 break;
603 if ((block || bcounter) && (block != prevblock+1)) {
604 /* Block order should be continuous */
605 tp.u.ack.block = htons(block = prevblock);
607 tp.opcode = htons(TFTP_ACK);
608 oport = ntohs(tr->udp.src);
609 udp_transmit(arptable[ARP_SERVER].ipaddr.s_addr, iport,
610 oport, TFTP_MIN_PACKET, &tp); /* ack */
611 if ((unsigned short)(block-prevblock) != 1) {
612 /* Retransmission or OACK, don't process via callback
613 * and don't change the value of prevblock. */
614 continue;
616 prevblock = block;
617 retry = 0; /* It's the right place to zero the timer? */
618 if ((rc = fnc(tr->u.data.download,
619 ++bcounter, len, len < packetsize)) >= 0)
620 return(rc);
621 if (len < packetsize) /* End of data */
622 return (1);
624 return (0);
626 #endif /* DOWNLOAD_PROTO_TFTP */
628 #ifdef RARP_NOT_BOOTP
629 /**************************************************************************
630 RARP - Get my IP address and load information
631 **************************************************************************/
632 int rarp()
634 int retry;
636 /* arp and rarp requests share the same packet structure. */
637 struct arprequest rarpreq;
639 memset(&rarpreq, 0, sizeof(rarpreq));
641 rarpreq.hwtype = htons(1);
642 rarpreq.protocol = htons(IP);
643 rarpreq.hwlen = ETHER_ADDR_SIZE;
644 rarpreq.protolen = 4;
645 rarpreq.opcode = htons(RARP_REQUEST);
646 memcpy(&rarpreq.shwaddr, arptable[ARP_CLIENT].node, ETHER_ADDR_SIZE);
647 /* sipaddr is already zeroed out */
648 memcpy(&rarpreq.thwaddr, arptable[ARP_CLIENT].node, ETHER_ADDR_SIZE);
649 /* tipaddr is already zeroed out */
651 for (retry = 0; retry < MAX_ARP_RETRIES; rfc951_sleep(++retry)) {
652 eth_transmit(broadcast, RARP, sizeof(rarpreq), &rarpreq);
654 if (await_reply(AWAIT_RARP, 0, rarpreq.shwaddr, TIMEOUT))
655 break;
658 if (retry < MAX_ARP_RETRIES) {
659 sprintf(kernel = kernel_buf, "/tftpboot/kernel.%I", arptable[ARP_CLIENT].ipaddr);
661 return (1);
663 return (0);
666 #else
668 /**************************************************************************
669 BOOTP - Get my IP address and load information
670 **************************************************************************/
671 int bootp()
673 int retry;
674 #ifndef NO_DHCP_SUPPORT
675 int retry1;
676 #endif /* NO_DHCP_SUPPORT */
677 struct bootp_t bp;
678 unsigned long starttime;
679 #ifdef T509HACK
680 int flag;
682 flag = 1;
683 #endif
684 memset(&bp, 0, sizeof(struct bootp_t));
685 bp.bp_op = BOOTP_REQUEST;
686 bp.bp_htype = 1;
687 bp.bp_hlen = ETHER_ADDR_SIZE;
688 bp.bp_xid = xid = starttime = currticks();
689 memcpy(bp.bp_hwaddr, arptable[ARP_CLIENT].node, ETHER_ADDR_SIZE);
690 #ifdef NO_DHCP_SUPPORT
691 memcpy(bp.bp_vend, rfc1533_cookie, 5); /* request RFC-style options */
692 #else
693 memcpy(bp.bp_vend, rfc1533_cookie, sizeof rfc1533_cookie); /* request RFC-style options */
694 memcpy(bp.bp_vend+sizeof rfc1533_cookie, dhcpdiscover, sizeof dhcpdiscover);
695 memcpy(bp.bp_vend+sizeof rfc1533_cookie +sizeof dhcpdiscover, rfc1533_end, sizeof rfc1533_end);
696 #endif /* NO_DHCP_SUPPORT */
698 for (retry = 0; retry < MAX_BOOTP_RETRIES; ) {
700 /* Clear out the Rx queue first. It contains nothing of
701 * interest, except possibly ARP requests from the DHCP/TFTP
702 * server. We use polling throughout Etherboot, so some time
703 * may have passed since we last polled the receive queue,
704 * which may now be filled with broadcast packets. This will
705 * cause the reply to the packets we are about to send to be
706 * lost immediately. Not very clever. */
707 await_reply(AWAIT_QDRAIN, 0, NULL, 0);
709 udp_transmit(IP_BROADCAST, BOOTP_CLIENT, BOOTP_SERVER,
710 sizeof(struct bootp_t), &bp);
711 #ifdef T509HACK
712 if (flag) {
713 flag--;
714 } else {
715 if (await_reply(AWAIT_BOOTP, 0, NULL, TIMEOUT))
716 return(1);
717 rfc951_sleep(++retry);
720 #else
721 #ifdef NO_DHCP_SUPPORT
722 if (await_reply(AWAIT_BOOTP, 0, NULL, TIMEOUT))
723 #else
724 if (await_reply(AWAIT_BOOTP, 0, NULL, TIMEOUT)){
725 if (dhcp_reply==DHCPOFFER){
726 dhcp_reply=0;
727 memcpy(bp.bp_vend, rfc1533_cookie, sizeof rfc1533_cookie);
728 memcpy(bp.bp_vend+sizeof rfc1533_cookie, dhcprequest, sizeof dhcprequest);
729 memcpy(bp.bp_vend+sizeof rfc1533_cookie +sizeof dhcprequest, rfc1533_end, sizeof rfc1533_end);
730 memcpy(bp.bp_vend+9, &dhcp_server, sizeof(in_addr));
731 memcpy(bp.bp_vend+15, &dhcp_addr, sizeof(in_addr));
732 for (retry1 = 0; retry1 < MAX_BOOTP_RETRIES;) {
733 udp_transmit(IP_BROADCAST, BOOTP_CLIENT, BOOTP_SERVER,
734 sizeof(struct bootp_t), &bp);
735 dhcp_reply=0;
736 if (await_reply(AWAIT_BOOTP, 0, NULL, TIMEOUT))
737 if (dhcp_reply==DHCPACK)
738 return(1);
739 rfc951_sleep(++retry1);
741 } else
742 #endif /* NO_DHCP_SUPPORT */
743 return(1);
744 #ifndef NO_DHCP_SUPPORT
746 rfc951_sleep(++retry);
748 #endif /* NO_DHCP_SUPPORT */
749 #endif
750 bp.bp_secs = htons((currticks()-starttime)/20);
752 return(0);
754 #endif /* RARP_NOT_BOOTP */
756 /**************************************************************************
757 AWAIT_REPLY - Wait until we get a response for our request
758 **************************************************************************/
759 int await_reply(int type, int ival, void *ptr, int timeout)
761 unsigned long time;
762 struct iphdr *ip;
763 struct udphdr *udp;
764 struct arprequest *arpreply;
765 struct bootp_t *bootpreply;
766 struct rpc_t *rpc;
767 unsigned short ptype;
769 unsigned int protohdrlen = ETHER_HDR_SIZE + sizeof(struct iphdr) +
770 sizeof(struct udphdr);
771 time = timeout + currticks();
772 /* The timeout check is done below. The timeout is only checked if
773 * there is no packet in the Rx queue. This assumes that eth_poll()
774 * needs a negligible amount of time. */
775 for (;;) {
776 if (eth_poll()) { /* We have something! */
777 /* Check for ARP - No IP hdr */
778 if (nic.packetlen >= ETHER_HDR_SIZE) {
779 ptype = ((unsigned short) nic.packet[12]) << 8
780 | ((unsigned short) nic.packet[13]);
781 } else continue; /* what else could we do with it? */
782 if ((nic.packetlen >= ETHER_HDR_SIZE +
783 sizeof(struct arprequest)) &&
784 (ptype == ARP) ) {
785 unsigned long tmp;
787 arpreply = (struct arprequest *)
788 &nic.packet[ETHER_HDR_SIZE];
789 if ((arpreply->opcode == ntohs(ARP_REPLY)) &&
790 !memcmp(arpreply->sipaddr, ptr, sizeof(in_addr)) &&
791 (type == AWAIT_ARP)) {
792 memcpy(arptable[ival].node, arpreply->shwaddr, ETHER_ADDR_SIZE);
793 return(1);
795 memcpy(&tmp, arpreply->tipaddr, sizeof(in_addr));
796 if ((arpreply->opcode == ntohs(ARP_REQUEST)) &&
797 (tmp == arptable[ARP_CLIENT].ipaddr.s_addr)) {
798 arpreply->opcode = htons(ARP_REPLY);
799 memcpy(arpreply->tipaddr, arpreply->sipaddr, sizeof(in_addr));
800 memcpy(arpreply->thwaddr, arpreply->shwaddr, ETHER_ADDR_SIZE);
801 memcpy(arpreply->sipaddr, &arptable[ARP_CLIENT].ipaddr, sizeof(in_addr));
802 memcpy(arpreply->shwaddr, arptable[ARP_CLIENT].node, ETHER_ADDR_SIZE);
803 eth_transmit(arpreply->thwaddr, ARP,
804 sizeof(struct arprequest),
805 arpreply);
806 #ifdef MDEBUG
807 memcpy(&tmp, arpreply->tipaddr, sizeof(in_addr));
808 printf("Sent ARP reply to: %I\n",tmp);
809 #endif MDEBUG
811 continue;
814 if (type == AWAIT_QDRAIN) {
815 continue;
818 /* Check for RARP - No IP hdr */
819 if ((type == AWAIT_RARP) &&
820 (nic.packetlen >= ETHER_HDR_SIZE +
821 sizeof(struct arprequest)) &&
822 (ptype == RARP)) {
823 arpreply = (struct arprequest *)
824 &nic.packet[ETHER_HDR_SIZE];
825 if ((arpreply->opcode == ntohs(RARP_REPLY)) &&
826 !memcmp(arpreply->thwaddr, ptr, ETHER_ADDR_SIZE)) {
827 memcpy(arptable[ARP_SERVER].node, arpreply->shwaddr, ETHER_ADDR_SIZE);
828 memcpy(& arptable[ARP_SERVER].ipaddr, arpreply->sipaddr, sizeof(in_addr));
829 memcpy(& arptable[ARP_CLIENT].ipaddr, arpreply->tipaddr, sizeof(in_addr));
830 return(1);
832 continue;
835 /* Anything else has IP header */
836 if ((nic.packetlen < protohdrlen) ||
837 (ptype != IP) ) continue;
838 ip = (struct iphdr *)&nic.packet[ETHER_HDR_SIZE];
839 if ((ip->verhdrlen != 0x45) ||
840 ipchksum((unsigned short *)ip, sizeof(struct iphdr)) ||
841 (ip->protocol != IP_UDP)) continue;
842 udp = (struct udphdr *)&nic.packet[ETHER_HDR_SIZE +
843 sizeof(struct iphdr)];
845 /* BOOTP ? */
846 bootpreply = (struct bootp_t *)&nic.packet[ETHER_HDR_SIZE];
847 if ((type == AWAIT_BOOTP) &&
848 (nic.packetlen >= (ETHER_HDR_SIZE +
849 #ifdef NO_DHCP_SUPPORT
850 sizeof(struct bootp_t))) &&
851 #else
852 sizeof(struct bootp_t))-DHCP_OPT_LEN) &&
853 #endif /* NO_DHCP_SUPPORT */
854 (ntohs(udp->dest) == BOOTP_CLIENT) &&
855 (bootpreply->bp_op == BOOTP_REPLY) &&
856 (bootpreply->bp_xid == xid)) {
857 arptable[ARP_CLIENT].ipaddr.s_addr =
858 bootpreply->bp_yiaddr.s_addr;
859 #ifndef NO_DHCP_SUPPORT
860 dhcp_addr.s_addr = bootpreply->bp_yiaddr.s_addr;
861 #endif /* NO_DHCP_SUPPORT */
862 netmask = default_netmask();
863 arptable[ARP_SERVER].ipaddr.s_addr =
864 bootpreply->bp_siaddr.s_addr;
865 memset(arptable[ARP_SERVER].node, 0, ETHER_ADDR_SIZE); /* Kill arp */
866 arptable[ARP_GATEWAY].ipaddr.s_addr =
867 bootpreply->bp_giaddr.s_addr;
868 memset(arptable[ARP_GATEWAY].node, 0, ETHER_ADDR_SIZE); /* Kill arp */
869 if (bootpreply->bp_file[0]) {
870 memcpy(kernel_buf, bootpreply->bp_file, 128);
871 kernel = kernel_buf;
873 memcpy((char *)BOOTP_DATA_ADDR, (char *)bootpreply, sizeof(struct bootpd_t));
874 decode_rfc1533(BOOTP_DATA_ADDR->bootp_reply.bp_vend,
875 #ifdef NO_DHCP_SUPPORT
876 0, BOOTP_VENDOR_LEN + MAX_BOOTP_EXTLEN, 1);
877 #else
878 0, DHCP_OPT_LEN + MAX_BOOTP_EXTLEN, 1);
879 #endif /* NO_DHCP_SUPPORT */
880 return(1);
883 #ifdef DOWNLOAD_PROTO_TFTP
884 /* TFTP ? */
885 if ((type == AWAIT_TFTP) &&
886 (ntohs(udp->dest) == ival)) return(1);
887 #endif /* DOWNLOAD_PROTO_TFTP */
889 #ifdef DOWNLOAD_PROTO_NFS
890 /* RPC ? */
891 rpc = (struct rpc_t *)&nic.packet[ETHER_HDR_SIZE];
892 if ((type == AWAIT_RPC) &&
893 (ntohs(udp->dest) == ival) &&
894 (*(unsigned long *)ptr == ntohl(rpc->u.reply.id)) &&
895 (ntohl(rpc->u.reply.type) == MSG_REPLY)) {
896 return (1);
898 #endif /* DOWNLOAD_PROTO_NFS */
900 } else {
901 /* Check for abort key only if the Rx queue is empty -
902 * as long as we have something to process, don't
903 * assume that something failed. It is unlikely that
904 * we have no processing time left between packets. */
905 if (iskey() && (getchar() == ESC))
906 #ifdef EMERGENCYDISKBOOT
907 exit(0);
908 #else
909 longjmp(jmp_bootmenu,1);
910 #endif
911 /* Do the timeout after at least a full queue walk. */
912 if ((timeout == 0) || (currticks() > time)) {
913 break;
917 return(0);
920 /**************************************************************************
921 DECODE_RFC1533 - Decodes RFC1533 header
922 **************************************************************************/
923 int decode_rfc1533(p, block, len, eof)
924 register unsigned char *p;
925 int block, len, eof;
927 static unsigned char *extdata = NULL, *extend = NULL;
928 unsigned char *extpath = NULL;
929 unsigned char *endp;
931 if (block == 0) {
932 #ifdef IMAGE_MENU
933 memset(imagelist, 0, sizeof(imagelist));
934 menudefault = useimagemenu = 0;
935 menutmo = -1;
936 #endif
937 #ifdef MOTD
938 memset(motd, 0, sizeof(motd));
939 #endif
940 end_of_rfc1533 = NULL;
941 vendorext_isvalid = 0;
942 if (memcmp(p, rfc1533_cookie, 4))
943 return(0); /* no RFC 1533 header found */
944 p += 4;
945 endp = p + len; }
946 else {
947 if (block == 1) {
948 if (memcmp(p, rfc1533_cookie, 4))
949 return(0); /* no RFC 1533 header found */
950 p += 4;
951 len -= 4; }
952 if (extend + len <= (unsigned char *)&(BOOTP_DATA_ADDR->bootp_extension[MAX_BOOTP_EXTLEN])) {
953 memcpy(extend, p, len);
954 extend += len;
955 } else {
956 printf("Overflow in vendor data buffer! Aborting...\n");
957 *extdata = RFC1533_END;
958 return(0);
960 p = extdata; endp = extend;
962 if (eof) {
963 while(p < endp) {
964 unsigned char c = *p;
965 if (c == RFC1533_PAD) {p++; continue;}
966 else if (c == RFC1533_END) {
967 end_of_rfc1533 = endp = p; continue; }
968 else if (c == RFC1533_NETMASK) {memcpy(&netmask, p+2, sizeof(in_addr));}
970 else if (c == RFC1533_GATEWAY) {
971 /* This is a little simplistic, but it will
972 usually be sufficient.
973 Take only the first entry */
974 if (TAG_LEN(p) >= sizeof(in_addr))
975 memcpy(&arptable[ARP_GATEWAY].ipaddr, p+2, sizeof(in_addr));
977 else if (c == RFC1533_EXTENSIONPATH)
978 extpath = p;
979 #ifndef NO_DHCP_SUPPORT
980 else if (c == RFC2132_MSG_TYPE)
981 { dhcp_reply=*(p+2);
983 else if (c == RFC2132_SRV_ID)
985 memcpy(&dhcp_server, p+2, sizeof(in_addr));
987 #endif /* NO_DHCP_SUPPORT */
988 else if (c == RFC1533_HOSTNAME)
990 hostname = p + 2;
991 hostnamelen = *(p + 1);
993 else if (c == RFC1533_VENDOR_MAGIC
994 #ifndef IMAGE_FREEBSD /* since FreeBSD uses tag 128 for swap definition */
995 && TAG_LEN(p) >= 6 &&
996 !memcmp(p+2,vendorext_magic,4) &&
997 p[6] == RFC1533_VENDOR_MAJOR
998 #endif
1000 vendorext_isvalid++;
1001 #ifdef IMAGE_FREEBSD
1002 else if (c == RFC1533_VENDOR_HOWTO) {
1003 freebsd_howto = ((p[2]*256+p[3])*256+p[4])*256+p[5];
1005 #endif
1006 #ifdef IMAGE_MENU
1007 else if (c == RFC1533_VENDOR_MNUOPTS) {
1008 parse_menuopts(p+2, TAG_LEN(p));
1010 else if (c >= RFC1533_VENDOR_IMG &&
1011 c<RFC1533_VENDOR_IMG+RFC1533_VENDOR_NUMOFIMG){
1012 imagelist[c - RFC1533_VENDOR_IMG] = p;
1013 useimagemenu++;
1015 #endif
1016 #ifdef MOTD
1017 else if (c >= RFC1533_VENDOR_MOTD &&
1018 c < RFC1533_VENDOR_MOTD +
1019 RFC1533_VENDOR_NUMOFMOTD)
1020 motd[c - RFC1533_VENDOR_MOTD] = p;
1021 #endif
1022 else {
1023 #if 0
1024 unsigned char *q;
1025 printf("Unknown RFC1533-tag ");
1026 for(q=p;q<p+2+TAG_LEN(p);q++)
1027 printf("%x ",*q);
1028 putchar('\n');
1029 #endif
1031 p += TAG_LEN(p) + 2;
1033 extdata = extend = endp;
1034 if (block == 0 && extpath != NULL) {
1035 char fname[64];
1036 memcpy(fname, extpath+2, TAG_LEN(extpath));
1037 fname[(int)TAG_LEN(extpath)] = '\000';
1038 printf("Loading BOOTP-extension file: %s\n",fname);
1039 download(fname,decode_rfc1533);
1042 return(-1); /* proceed with next block */
1045 /**************************************************************************
1046 IPCHKSUM - Checksum IP Header
1047 **************************************************************************/
1048 unsigned short ipchksum(ip, len)
1049 register unsigned short *ip;
1050 register int len;
1052 unsigned long sum = 0;
1053 len >>= 1;
1054 while (len--) {
1055 sum += *(ip++);
1056 if (sum > 0xFFFF)
1057 sum -= 0xFFFF;
1059 return((~sum) & 0x0000FFFF);
1062 /**************************************************************************
1063 RFC951_SLEEP - sleep for expotentially longer times
1064 **************************************************************************/
1065 void rfc951_sleep(exp)
1066 int exp;
1068 static long seed = 0;
1069 long q;
1070 unsigned long tmo;
1072 #ifdef BACKOFF_LIMIT
1073 if (exp > BACKOFF_LIMIT)
1074 exp = BACKOFF_LIMIT;
1075 #endif
1076 if (!seed) /* Initialize linear congruential generator */
1077 seed = currticks() + *(long *)&arptable[ARP_CLIENT].node
1078 + ((short *)arptable[ARP_CLIENT].node)[2];
1079 /* simplified version of the LCG given in Bruce Scheier's
1080 "Applied Cryptography" */
1081 q = seed/53668;
1082 if ((seed = 40014*(seed-53668*q) - 12211*q) < 0) seed += 2147483563l;
1083 /* compute mask */
1084 for (tmo = 63; tmo <= 60*TICKS_PER_SEC && --exp > 0; tmo = 2*tmo+1);
1085 /* sleep */
1086 printf("<sleep>\n");
1088 for (tmo = (tmo&seed)+currticks(); currticks() < tmo; )
1089 if (iskey() && (getchar() == ESC)) longjmp(jmp_bootmenu,1);
1090 return;
1093 /**************************************************************************
1094 CLEANUP_NET - shut down networking
1095 **************************************************************************/
1096 void cleanup_net(void)
1098 #ifdef DOWNLOAD_PROTO_NFS
1099 nfs_umountall(ARP_SERVER);
1100 #endif
1101 eth_disable();
1102 eth_reset();
1105 /**************************************************************************
1106 CLEANUP - shut down etherboot so that the OS may be called right away
1107 **************************************************************************/
1108 void cleanup(void)
1110 #if defined(ANSIESC) && defined(CONSOLE_CRT)
1111 ansi_reset();
1112 #endif
1116 * Local variables:
1117 * c-basic-offset: 8
1118 * End: