diff options
Diffstat (limited to 'contrib/baremetal/main.c')
-rw-r--r-- | contrib/baremetal/main.c | 1119 |
1 files changed, 0 insertions, 1119 deletions
diff --git a/contrib/baremetal/main.c b/contrib/baremetal/main.c deleted file mode 100644 index 7b0de44c1..000000000 --- a/contrib/baremetal/main.c +++ /dev/null @@ -1,1119 +0,0 @@ -/************************************************************************** -ETHERBOOT - BOOTP/TFTP Bootstrap Program - -Author: Martin Renters - Date: Dec/93 - -Literature dealing with the network protocols: - ARP - RFC826 - RARP - RFC903 - UDP - RFC768 - BOOTP - RFC951, RFC2132 (vendor extensions) - DHCP - RFC2131, RFC2132 (options) - TFTP - RFC1350, RFC2347 (options), RFC2348 (blocksize), RFC2349 (tsize) - RPC - RFC1831, RFC1832 (XDR), RFC1833 (rpcbind/portmapper) - NFS - RFC1094, RFC1813 (v3, useful for clarifications, not implemented) - -**************************************************************************/ - -/* #define MDEBUG */ - -#include "etherboot.h" -#include "nic.h" - -int jmp_bootmenu[10]; - -struct arptable_t arptable[MAX_ARP]; - -const char *kernel; -char kernel_buf[128]; -struct rom_info rom; - -#ifdef IMAGE_MENU -static char *imagelist[RFC1533_VENDOR_NUMOFIMG]; -static int useimagemenu; -int menutmo,menudefault; -unsigned char *defparams = NULL; -int defparams_max = 0; -#endif -#ifdef MOTD -char *motd[RFC1533_VENDOR_NUMOFMOTD]; -#endif -#ifdef IMAGE_FREEBSD -int freebsd_howto = 0; -#endif -int vendorext_isvalid; -char config_buffer[TFTP_MAX_PACKET+1]; /* +1 for null byte */ -unsigned long netmask; -char *hostname = ""; -int hostnamelen = 0; -#if defined(ETHERBOOT16) || defined(INTERNAL_BOOTP_DATA) -struct bootpd_t bootp_data; -#endif -unsigned long xid; -unsigned char *end_of_rfc1533 = NULL; -#ifndef NO_DHCP_SUPPORT -int dhcp_reply; -in_addr dhcp_server = { 0L }; -in_addr dhcp_addr = { 0L }; -#endif /* NO_DHCP_SUPPORT */ - -unsigned char vendorext_magic[] = {0xE4,0x45,0x74,0x68}; /* äEth */ -#ifdef NO_DHCP_SUPPORT -char rfc1533_cookie[5] = { RFC1533_COOKIE, RFC1533_END }; -#else -char rfc1533_cookie[] = { RFC1533_COOKIE}; -char rfc1533_end[]={RFC1533_END }; -static const char dhcpdiscover[]={ - RFC2132_MSG_TYPE,1,DHCPDISCOVER, - RFC2132_MAX_SIZE,2, /* request as much as we can */ - sizeof(struct bootpd_t) / 256, sizeof(struct bootpd_t) % 256, - RFC2132_PARAM_LIST,4,RFC1533_NETMASK,RFC1533_GATEWAY, - RFC1533_HOSTNAME - }; -static const char dhcprequest []={ - RFC2132_MSG_TYPE,1,DHCPREQUEST, - RFC2132_SRV_ID,4,0,0,0,0, - RFC2132_REQ_ADDR,4,0,0,0,0, - RFC2132_MAX_SIZE,2, /* request as much as we can */ - sizeof(struct bootpd_t) / 256, sizeof(struct bootpd_t) % 256, - /* request parameters */ - RFC2132_PARAM_LIST, -#ifdef IMAGE_FREEBSD - /* 4 standard + 6 vendortags + 8 motd + 16 menu items */ - 4 + 6 + 8 + 16, -#else - /* 4 standard + 5 vendortags + 8 motd + 16 menu items */ - 4 + 5 + 8 + 16, -#endif - /* Standard parameters */ - RFC1533_NETMASK, RFC1533_GATEWAY, - RFC1533_HOSTNAME, - RFC1533_ROOTPATH, /* only passed to the booted image */ - /* Etherboot vendortags */ - RFC1533_VENDOR_MAGIC, - RFC1533_VENDOR_ADDPARM, - RFC1533_VENDOR_ETHDEV, -#ifdef IMAGE_FREEBSD - RFC1533_VENDOR_HOWTO, -#endif - RFC1533_VENDOR_MNUOPTS, RFC1533_VENDOR_SELECTION, - /* 8 MOTD entries */ - RFC1533_VENDOR_MOTD, - RFC1533_VENDOR_MOTD+1, - RFC1533_VENDOR_MOTD+2, - RFC1533_VENDOR_MOTD+3, - RFC1533_VENDOR_MOTD+4, - RFC1533_VENDOR_MOTD+5, - RFC1533_VENDOR_MOTD+6, - RFC1533_VENDOR_MOTD+7, - /* 16 image entries */ - RFC1533_VENDOR_IMG, - RFC1533_VENDOR_IMG+1, - RFC1533_VENDOR_IMG+2, - RFC1533_VENDOR_IMG+3, - RFC1533_VENDOR_IMG+4, - RFC1533_VENDOR_IMG+5, - RFC1533_VENDOR_IMG+6, - RFC1533_VENDOR_IMG+7, - RFC1533_VENDOR_IMG+8, - RFC1533_VENDOR_IMG+9, - RFC1533_VENDOR_IMG+10, - RFC1533_VENDOR_IMG+11, - RFC1533_VENDOR_IMG+12, - RFC1533_VENDOR_IMG+13, - RFC1533_VENDOR_IMG+14, - RFC1533_VENDOR_IMG+15, - }; - -#endif /* NO_DHCP_SUPPORT */ -static const char broadcast[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; - -/************************************************************************** -MAIN - Kick off routine -**************************************************************************/ -int main(void) -{ - char *p; - static int card_retries = 0; - int i; - - for (p=_edata; p<_end; p++) - *p = 0; /* Zero BSS */ - -#ifdef CONSOLE_SERIAL - (void)serial_init(); -#endif - -#ifdef DELIMITERLINES - for (i=0; i<80; i++) putchar('='); -#endif - -#ifdef ETHERBOOT32 - rom = *(struct rom_info *)ROM_INFO_LOCATION; - printf("ROM segment %#x length %#x reloc %#x\n", rom.rom_segment, - rom.rom_length << 1, ((unsigned long)_start) >> 4); -#endif -#ifdef ETHERBOOT16 - fmemcpy(&rom, (Address)ROM_INFO_LOCATION, sizeof(rom)); - printf("ROM segment %#x length %#x\n", rom.rom_segment, - rom.rom_length << 1); -#endif -#ifdef ASK_BOOT - while (1) { - int c; - unsigned long time; - printf(ASK_PROMPT); -#if ASK_BOOT > 0 - for (time = currticks() + ASK_BOOT*TICKS_PER_SEC; !iskey(); ) - if (currticks() > time) { - c = ANS_DEFAULT; - goto done; - } -#endif - c = getchar(); - if ((c >= 'a') && (c <= 'z')) c &= 0x5F; - if (c == '\n') c = ANS_DEFAULT; -done: - if ((c >= ' ') && (c <= '~')) putchar(c); - putchar('\n'); - if (c == ANS_LOCAL) - exit(0); - if (c == ANS_NETWORK) - break; - } -#endif -#if (TRY_FLOPPY_FIRST > 0) && defined(FLOPPY) - disk_init(); - printf("Trying floppy"); - for (i = TRY_FLOPPY_FIRST; i-- > 0; ) { - putchar('.'); - if (disk_read(0, 0, 0, 0, ((char *) FLOPPY_BOOT_LOCATION)) != 0x8000) { - printf("using floppy\n"); - exit(0); - } - } - printf("no floppy\n"); -#endif /* TRY_FLOPPY_FIRST && FLOPPY */ - print_config(); - gateA20_set(); -#ifdef EMERGENCYDISKBOOT - if (!eth_probe()) { - printf("No adapter found\n"); - exit(0); - } -#else - while (!eth_probe()) { - printf("No adapter found"); - if (!setjmp(jmp_bootmenu)) - rfc951_sleep(++card_retries); - } -#endif - kernel = DEFAULT_BOOTFILE; - while (1) { - if ((i = setjmp(jmp_bootmenu)) != 0) { -#if defined(ANSIESC) && defined(CONSOLE_CRT) - ansi_reset(); -#endif - bootmenu(--i); - } else { - load(); - } -#if defined(ANSIESC) && defined(CONSOLE_CRT) - ansi_reset(); -#endif - } -} - -/************************************************************************** -LOADKERNEL - Try to load kernel image -**************************************************************************/ -#ifndef FLOPPY -#define loadkernel(s) download((s),downloadkernel) -#else -static int loadkernel(const char *fname) -{ - if (!memcmp(fname,"/dev/",5) && fname[6] == 'd') { - int dev, part = 0; - if (fname[5] == 'f') { - if ((dev = fname[7] - '0') < 0 || dev > 3) - goto nodisk; } - else if (fname[5] == 'h' || fname[5] == 's') { - if ((dev = 0x80 + fname[7] - 'a') < 0x80 || dev > 0x83) - goto nodisk; - if (fname[8]) { - part = fname[8] - '0'; - if (fname[9]) - part = 10*part + fname[9] - '0'; } - /* bootdisk cannot cope with more than eight partitions */ - if (part < 0 || part > 8) - goto nodisk; } - else - goto nodisk; - return(bootdisk(dev,part)); } -nodisk: - return download(fname, downloadkernel); -} -#endif - -/************************************************************************** -LOAD - Try to get booted -**************************************************************************/ -void load() -{ - static int bootp_completed = 0; - - /* Find a server to get BOOTP reply from */ - if (!bootp_completed || - !arptable[ARP_CLIENT].ipaddr.s_addr || !arptable[ARP_SERVER].ipaddr.s_addr) { -retry: - bootp_completed = 0; -#ifdef RARP_NOT_BOOTP - printf("Searching for server (RARP)...\n"); -#else -#ifndef NO_DHCP_SUPPORT - printf("Searching for server (DHCP)...\n"); -#else - printf("Searching for server (BOOTP)...\n"); -#endif -#endif - -#ifdef RARP_NOT_BOOTP - if (!rarp()) { -#else - if (!bootp()) { -#endif - printf("No Server found\n"); -#ifdef EMERGENCYDISKBOOT - exit(0); -#else - goto retry; -#endif - } - bootp_completed++; - } - printf("Me: %I, Server: %I", - arptable[ARP_CLIENT].ipaddr.s_addr, - arptable[ARP_SERVER].ipaddr.s_addr); - if (BOOTP_DATA_ADDR->bootp_reply.bp_giaddr.s_addr) - printf(", Relay: %I", - BOOTP_DATA_ADDR->bootp_reply.bp_giaddr.s_addr); - if (arptable[ARP_GATEWAY].ipaddr.s_addr) - printf(", Gateway %I", arptable[ARP_GATEWAY].ipaddr.s_addr); - putchar('\n'); - -#ifdef MDEBUG - printf("\n=>>"); getchar(); -#endif - -#ifdef MOTD - if (vendorext_isvalid) - show_motd(); -#endif - /* Now use TFTP to load file */ -#ifdef IMAGE_MENU - if (vendorext_isvalid && useimagemenu) { - selectImage(imagelist); - bootp_completed = 0; - } -#endif -#ifdef DOWNLOAD_PROTO_NFS - rpc_init(); -#endif - for (;;) { - printf("Loading %s ",kernel); - while (!loadkernel(kernel)) { - printf("Unable to load file.\n"); - sleep(2); /* lay off server for a while */ - } - } -} - -/************************************************************************** -DEFAULT_NETMASK - Return default netmask for IP address -**************************************************************************/ -static inline unsigned long default_netmask(void) -{ - int net = ntohl(arptable[ARP_CLIENT].ipaddr.s_addr) >> 24; - if (net <= 127) - return(htonl(0xff000000)); - else if (net < 192) - return(htonl(0xffff0000)); - else - return(htonl(0xffffff00)); -} - -/************************************************************************** -UDP_TRANSMIT - Send a UDP datagram -**************************************************************************/ -int udp_transmit(unsigned long destip, unsigned int srcsock, - unsigned int destsock, int len, const void *buf) -{ - struct iphdr *ip; - struct udphdr *udp; - struct arprequest arpreq; - int arpentry, i; - int retry; - - ip = (struct iphdr *)buf; - udp = (struct udphdr *)((long)buf + sizeof(struct iphdr)); - ip->verhdrlen = 0x45; - ip->service = 0; - ip->len = htons(len); - ip->ident = 0; - ip->frags = 0; - ip->ttl = 60; - ip->protocol = IP_UDP; - ip->chksum = 0; - ip->src.s_addr = arptable[ARP_CLIENT].ipaddr.s_addr; - ip->dest.s_addr = destip; - ip->chksum = ipchksum((unsigned short *)buf, sizeof(struct iphdr)); - udp->src = htons(srcsock); - udp->dest = htons(destsock); - udp->len = htons(len - sizeof(struct iphdr)); - udp->chksum = 0; - if (destip == IP_BROADCAST) { - eth_transmit(broadcast, IP, len, buf); - } else { - if (((destip & netmask) != - (arptable[ARP_CLIENT].ipaddr.s_addr & netmask)) && - arptable[ARP_GATEWAY].ipaddr.s_addr) - destip = arptable[ARP_GATEWAY].ipaddr.s_addr; - for(arpentry = 0; arpentry<MAX_ARP; arpentry++) - if (arptable[arpentry].ipaddr.s_addr == destip) break; - if (arpentry == MAX_ARP) { - printf("%I is not in my arp table!\n", destip); - return(0); - } - for (i = 0; i<ETHER_ADDR_SIZE; i++) - if (arptable[arpentry].node[i]) break; - if (i == ETHER_ADDR_SIZE) { /* Need to do arp request */ - arpreq.hwtype = htons(1); - arpreq.protocol = htons(IP); - arpreq.hwlen = ETHER_ADDR_SIZE; - arpreq.protolen = 4; - arpreq.opcode = htons(ARP_REQUEST); - memcpy(arpreq.shwaddr, arptable[ARP_CLIENT].node, ETHER_ADDR_SIZE); - memcpy(arpreq.sipaddr, &arptable[ARP_CLIENT].ipaddr, sizeof(in_addr)); - memset(arpreq.thwaddr, 0, ETHER_ADDR_SIZE); - memcpy(arpreq.tipaddr, &destip, sizeof(in_addr)); - for (retry = 1; retry <= MAX_ARP_RETRIES; retry++) { - eth_transmit(broadcast, ARP, sizeof(arpreq), - &arpreq); - if (await_reply(AWAIT_ARP, arpentry, - arpreq.tipaddr, TIMEOUT)) goto xmit; - rfc951_sleep(retry); - /* We have slept for a while - the packet may - * have arrived by now. If not, we have at - * least some room in the Rx buffer for the - * next reply. */ - if (await_reply(AWAIT_ARP, arpentry, - arpreq.tipaddr, 0)) goto xmit; - } - return(0); - } -xmit: - eth_transmit(arptable[arpentry].node, IP, len, buf); - } - return(1); -} - -/************************************************************************** -DOWNLOADKERNEL - Try to load file -**************************************************************************/ -int downloadkernel(data, block, len, eof) - unsigned char *data; - int block, len, eof; -{ -#ifdef SIZEINDICATOR - static int rlen = 0; - - if (!(block % 4) || eof) { - int size; - size = ((block-1) * rlen + len) / 1024; - - putchar('\b'); - putchar('\b'); - putchar('\b'); - putchar('\b'); - - putchar('0' + (size/1000)%10); - putchar('0' + (size/100)%10); - putchar('0' + (size/10)%10); - putchar('0' + (size/1)%10); - } -#endif - if (block == 1) - { -#ifdef SIZEINDICATOR - rlen=len; -#endif - if (!eof && ( -#ifdef TAGGED_IMAGE - *((unsigned long *)data) == 0x1B031336L || -#endif -#ifdef ELF_IMAGE - *((unsigned long *)data) == 0x464C457FL || -#endif -#ifdef AOUT_IMAGE - *((unsigned short *)data) == 0x010BL || -#endif - ((unsigned short *)data)[255] == 0xAA55)) - { - ; - } - else if (eof) - { - memcpy(config_buffer, data, len); - config_buffer[len] = 0; - return (1); /* done */ - } - else - { - printf("error: not a tagged image\n"); - return(0); /* error */ - } - } - if (len != 0) { - if (!os_download(block, data, len)) - return(0); /* error */ - } - if (eof) { - os_download(block+1, data, 0); /* does not return */ - return(0); /* error */ - } - return(-1); /* there is more data */ -} - -#ifdef DOWNLOAD_PROTO_TFTP -/************************************************************************** -TFTP - Download extended BOOTP data, or kernel image -**************************************************************************/ -int tftp(const char *name, int (*fnc)(unsigned char *, int, int, int)) -{ - int retry = 0; - static unsigned short iport = 2000; - unsigned short oport; - unsigned short len, block = 0, prevblock = 0; - int bcounter = 0; - struct tftp_t *tr; - struct tftp_t tp; - int rc; - int packetsize = TFTP_DEFAULTSIZE_PACKET; - - /* Clear out the Rx queue first. It contains nothing of interest, - * except possibly ARP requests from the DHCP/TFTP server. We use - * polling throughout Etherboot, so some time may have passed since we - * last polled the receive queue, which may now be filled with - * broadcast packets. This will cause the reply to the packets we are - * about to send to be lost immediately. Not very clever. */ - await_reply(AWAIT_QDRAIN, 0, NULL, 0); - - tp.opcode = htons(TFTP_RRQ); - len = (sprintf((char *)tp.u.rrq, "%s%coctet%cblksize%c%d", - name, 0, 0, 0, TFTP_MAX_PACKET) - ((char *)&tp)) + 1; - if (!udp_transmit(arptable[ARP_SERVER].ipaddr.s_addr, ++iport, - TFTP_PORT, len, &tp)) - return (0); - for (;;) - { -#ifdef CONGESTED - if (!await_reply(AWAIT_TFTP, iport, NULL, (block ? TFTP_REXMT : TIMEOUT))) -#else - if (!await_reply(AWAIT_TFTP, iport, NULL, TIMEOUT)) -#endif - { - if (!block && retry++ < MAX_TFTP_RETRIES) - { /* maybe initial request was lost */ - rfc951_sleep(retry); - if (!udp_transmit(arptable[ARP_SERVER].ipaddr.s_addr, - ++iport, TFTP_PORT, len, &tp)) - return (0); - continue; - } -#ifdef CONGESTED - if (block && ((retry += TFTP_REXMT) < TFTP_TIMEOUT)) - { /* we resend our last ack */ -#ifdef MDEBUG - printf("<REXMT>\n"); -#endif - udp_transmit(arptable[ARP_SERVER].ipaddr.s_addr, - iport, oport, - TFTP_MIN_PACKET, &tp); - continue; - } -#endif - break; /* timeout */ - } - tr = (struct tftp_t *)&nic.packet[ETHER_HDR_SIZE]; - if (tr->opcode == ntohs(TFTP_ERROR)) - { - printf("TFTP error %d (%s)\n", - ntohs(tr->u.err.errcode), - tr->u.err.errmsg); - break; - } - - if (tr->opcode == ntohs(TFTP_OACK)) { - char *p = tr->u.oack.data, *e; - - if (prevblock) /* shouldn't happen */ - continue; /* ignore it */ - len = ntohs(tr->udp.len) - sizeof(struct udphdr) - 2; - if (len > TFTP_MAX_PACKET) - goto noak; - e = p + len; - while (*p != '\000' && p < e) { - if (!strcasecmp("blksize", p)) { - p += 8; - if ((packetsize = getdec(&p)) < - TFTP_DEFAULTSIZE_PACKET) - goto noak; - while (p < e && *p) p++; - if (p < e) - p++; - } - else { - noak: - tp.opcode = htons(TFTP_ERROR); - tp.u.err.errcode = 8; - len = (sprintf((char *)tp.u.err.errmsg, - "RFC1782 error") - - ((char *)&tp)) + 1; - udp_transmit(arptable[ARP_SERVER].ipaddr.s_addr, - iport, ntohs(tr->udp.src), - len, &tp); - return (0); - } - } - if (p > e) - goto noak; - block = tp.u.ack.block = 0; /* this ensures, that */ - /* the packet does not get */ - /* processed as data! */ - } - else if (tr->opcode == ntohs(TFTP_DATA)) { - len = ntohs(tr->udp.len) - sizeof(struct udphdr) - 4; - if (len > packetsize) /* shouldn't happen */ - continue; /* ignore it */ - block = ntohs(tp.u.ack.block = tr->u.data.block); } - else /* neither TFTP_OACK nor TFTP_DATA */ - break; - - if ((block || bcounter) && (block != prevblock+1)) { - /* Block order should be continuous */ - tp.u.ack.block = htons(block = prevblock); - } - tp.opcode = htons(TFTP_ACK); - oport = ntohs(tr->udp.src); - udp_transmit(arptable[ARP_SERVER].ipaddr.s_addr, iport, - oport, TFTP_MIN_PACKET, &tp); /* ack */ - if ((unsigned short)(block-prevblock) != 1) { - /* Retransmission or OACK, don't process via callback - * and don't change the value of prevblock. */ - continue; - } - prevblock = block; - retry = 0; /* It's the right place to zero the timer? */ - if ((rc = fnc(tr->u.data.download, - ++bcounter, len, len < packetsize)) >= 0) - return(rc); - if (len < packetsize) /* End of data */ - return (1); - } - return (0); -} -#endif /* DOWNLOAD_PROTO_TFTP */ - -#ifdef RARP_NOT_BOOTP -/************************************************************************** -RARP - Get my IP address and load information -**************************************************************************/ -int rarp() -{ - int retry; - - /* arp and rarp requests share the same packet structure. */ - struct arprequest rarpreq; - - memset(&rarpreq, 0, sizeof(rarpreq)); - - rarpreq.hwtype = htons(1); - rarpreq.protocol = htons(IP); - rarpreq.hwlen = ETHER_ADDR_SIZE; - rarpreq.protolen = 4; - rarpreq.opcode = htons(RARP_REQUEST); - memcpy(&rarpreq.shwaddr, arptable[ARP_CLIENT].node, ETHER_ADDR_SIZE); - /* sipaddr is already zeroed out */ - memcpy(&rarpreq.thwaddr, arptable[ARP_CLIENT].node, ETHER_ADDR_SIZE); - /* tipaddr is already zeroed out */ - - for (retry = 0; retry < MAX_ARP_RETRIES; rfc951_sleep(++retry)) { - eth_transmit(broadcast, RARP, sizeof(rarpreq), &rarpreq); - - if (await_reply(AWAIT_RARP, 0, rarpreq.shwaddr, TIMEOUT)) - break; - } - - if (retry < MAX_ARP_RETRIES) { - sprintf(kernel = kernel_buf, "/tftpboot/kernel.%I", arptable[ARP_CLIENT].ipaddr); - - return (1); - } - return (0); -} - -#else - -/************************************************************************** -BOOTP - Get my IP address and load information -**************************************************************************/ -int bootp() -{ - int retry; -#ifndef NO_DHCP_SUPPORT - int retry1; -#endif /* NO_DHCP_SUPPORT */ - struct bootp_t bp; - unsigned long starttime; -#ifdef T509HACK - int flag; - - flag = 1; -#endif - memset(&bp, 0, sizeof(struct bootp_t)); - bp.bp_op = BOOTP_REQUEST; - bp.bp_htype = 1; - bp.bp_hlen = ETHER_ADDR_SIZE; - bp.bp_xid = xid = starttime = currticks(); - memcpy(bp.bp_hwaddr, arptable[ARP_CLIENT].node, ETHER_ADDR_SIZE); -#ifdef NO_DHCP_SUPPORT - memcpy(bp.bp_vend, rfc1533_cookie, 5); /* request RFC-style options */ -#else - memcpy(bp.bp_vend, rfc1533_cookie, sizeof rfc1533_cookie); /* request RFC-style options */ - memcpy(bp.bp_vend+sizeof rfc1533_cookie, dhcpdiscover, sizeof dhcpdiscover); - memcpy(bp.bp_vend+sizeof rfc1533_cookie +sizeof dhcpdiscover, rfc1533_end, sizeof rfc1533_end); -#endif /* NO_DHCP_SUPPORT */ - - for (retry = 0; retry < MAX_BOOTP_RETRIES; ) { - - /* Clear out the Rx queue first. It contains nothing of - * interest, except possibly ARP requests from the DHCP/TFTP - * server. We use polling throughout Etherboot, so some time - * may have passed since we last polled the receive queue, - * which may now be filled with broadcast packets. This will - * cause the reply to the packets we are about to send to be - * lost immediately. Not very clever. */ - await_reply(AWAIT_QDRAIN, 0, NULL, 0); - - udp_transmit(IP_BROADCAST, BOOTP_CLIENT, BOOTP_SERVER, - sizeof(struct bootp_t), &bp); -#ifdef T509HACK - if (flag) { - flag--; - } else { - if (await_reply(AWAIT_BOOTP, 0, NULL, TIMEOUT)) - return(1); - rfc951_sleep(++retry); - - } -#else -#ifdef NO_DHCP_SUPPORT - if (await_reply(AWAIT_BOOTP, 0, NULL, TIMEOUT)) -#else - if (await_reply(AWAIT_BOOTP, 0, NULL, TIMEOUT)){ - if (dhcp_reply==DHCPOFFER){ - dhcp_reply=0; - memcpy(bp.bp_vend, rfc1533_cookie, sizeof rfc1533_cookie); - memcpy(bp.bp_vend+sizeof rfc1533_cookie, dhcprequest, sizeof dhcprequest); - memcpy(bp.bp_vend+sizeof rfc1533_cookie +sizeof dhcprequest, rfc1533_end, sizeof rfc1533_end); - memcpy(bp.bp_vend+9, &dhcp_server, sizeof(in_addr)); - memcpy(bp.bp_vend+15, &dhcp_addr, sizeof(in_addr)); - for (retry1 = 0; retry1 < MAX_BOOTP_RETRIES;) { - udp_transmit(IP_BROADCAST, BOOTP_CLIENT, BOOTP_SERVER, - sizeof(struct bootp_t), &bp); - dhcp_reply=0; - if (await_reply(AWAIT_BOOTP, 0, NULL, TIMEOUT)) - if (dhcp_reply==DHCPACK) - return(1); - rfc951_sleep(++retry1); - } - } else -#endif /* NO_DHCP_SUPPORT */ - return(1); -#ifndef NO_DHCP_SUPPORT - } - rfc951_sleep(++retry); - -#endif /* NO_DHCP_SUPPORT */ -#endif - bp.bp_secs = htons((currticks()-starttime)/20); - } - return(0); -} -#endif /* RARP_NOT_BOOTP */ - -/************************************************************************** -AWAIT_REPLY - Wait until we get a response for our request -**************************************************************************/ -int await_reply(int type, int ival, void *ptr, int timeout) -{ - unsigned long time; - struct iphdr *ip; - struct udphdr *udp; - struct arprequest *arpreply; - struct bootp_t *bootpreply; - struct rpc_t *rpc; - unsigned short ptype; - - unsigned int protohdrlen = ETHER_HDR_SIZE + sizeof(struct iphdr) + - sizeof(struct udphdr); - time = timeout + currticks(); - /* The timeout check is done below. The timeout is only checked if - * there is no packet in the Rx queue. This assumes that eth_poll() - * needs a negligible amount of time. */ - for (;;) { - if (eth_poll()) { /* We have something! */ - /* Check for ARP - No IP hdr */ - if (nic.packetlen >= ETHER_HDR_SIZE) { - ptype = ((unsigned short) nic.packet[12]) << 8 - | ((unsigned short) nic.packet[13]); - } else continue; /* what else could we do with it? */ - if ((nic.packetlen >= ETHER_HDR_SIZE + - sizeof(struct arprequest)) && - (ptype == ARP) ) { - unsigned long tmp; - - arpreply = (struct arprequest *) - &nic.packet[ETHER_HDR_SIZE]; - if ((arpreply->opcode == ntohs(ARP_REPLY)) && - !memcmp(arpreply->sipaddr, ptr, sizeof(in_addr)) && - (type == AWAIT_ARP)) { - memcpy(arptable[ival].node, arpreply->shwaddr, ETHER_ADDR_SIZE); - return(1); - } - memcpy(&tmp, arpreply->tipaddr, sizeof(in_addr)); - if ((arpreply->opcode == ntohs(ARP_REQUEST)) && - (tmp == arptable[ARP_CLIENT].ipaddr.s_addr)) { - arpreply->opcode = htons(ARP_REPLY); - memcpy(arpreply->tipaddr, arpreply->sipaddr, sizeof(in_addr)); - memcpy(arpreply->thwaddr, arpreply->shwaddr, ETHER_ADDR_SIZE); - memcpy(arpreply->sipaddr, &arptable[ARP_CLIENT].ipaddr, sizeof(in_addr)); - memcpy(arpreply->shwaddr, arptable[ARP_CLIENT].node, ETHER_ADDR_SIZE); - eth_transmit(arpreply->thwaddr, ARP, - sizeof(struct arprequest), - arpreply); -#ifdef MDEBUG - memcpy(&tmp, arpreply->tipaddr, sizeof(in_addr)); - printf("Sent ARP reply to: %I\n",tmp); -#endif MDEBUG - } - continue; - } - - if (type == AWAIT_QDRAIN) { - continue; - } - - /* Check for RARP - No IP hdr */ - if ((type == AWAIT_RARP) && - (nic.packetlen >= ETHER_HDR_SIZE + - sizeof(struct arprequest)) && - (ptype == RARP)) { - arpreply = (struct arprequest *) - &nic.packet[ETHER_HDR_SIZE]; - if ((arpreply->opcode == ntohs(RARP_REPLY)) && - !memcmp(arpreply->thwaddr, ptr, ETHER_ADDR_SIZE)) { - memcpy(arptable[ARP_SERVER].node, arpreply->shwaddr, ETHER_ADDR_SIZE); - memcpy(& arptable[ARP_SERVER].ipaddr, arpreply->sipaddr, sizeof(in_addr)); - memcpy(& arptable[ARP_CLIENT].ipaddr, arpreply->tipaddr, sizeof(in_addr)); - return(1); - } - continue; - } - - /* Anything else has IP header */ - if ((nic.packetlen < protohdrlen) || - (ptype != IP) ) continue; - ip = (struct iphdr *)&nic.packet[ETHER_HDR_SIZE]; - if ((ip->verhdrlen != 0x45) || - ipchksum((unsigned short *)ip, sizeof(struct iphdr)) || - (ip->protocol != IP_UDP)) continue; - udp = (struct udphdr *)&nic.packet[ETHER_HDR_SIZE + - sizeof(struct iphdr)]; - - /* BOOTP ? */ - bootpreply = (struct bootp_t *)&nic.packet[ETHER_HDR_SIZE]; - if ((type == AWAIT_BOOTP) && - (nic.packetlen >= (ETHER_HDR_SIZE + -#ifdef NO_DHCP_SUPPORT - sizeof(struct bootp_t))) && -#else - sizeof(struct bootp_t))-DHCP_OPT_LEN) && -#endif /* NO_DHCP_SUPPORT */ - (ntohs(udp->dest) == BOOTP_CLIENT) && - (bootpreply->bp_op == BOOTP_REPLY) && - (bootpreply->bp_xid == xid)) { - arptable[ARP_CLIENT].ipaddr.s_addr = - bootpreply->bp_yiaddr.s_addr; -#ifndef NO_DHCP_SUPPORT - dhcp_addr.s_addr = bootpreply->bp_yiaddr.s_addr; -#endif /* NO_DHCP_SUPPORT */ - netmask = default_netmask(); - arptable[ARP_SERVER].ipaddr.s_addr = - bootpreply->bp_siaddr.s_addr; - memset(arptable[ARP_SERVER].node, 0, ETHER_ADDR_SIZE); /* Kill arp */ - arptable[ARP_GATEWAY].ipaddr.s_addr = - bootpreply->bp_giaddr.s_addr; - memset(arptable[ARP_GATEWAY].node, 0, ETHER_ADDR_SIZE); /* Kill arp */ - if (bootpreply->bp_file[0]) { - memcpy(kernel_buf, bootpreply->bp_file, 128); - kernel = kernel_buf; - } - memcpy((char *)BOOTP_DATA_ADDR, (char *)bootpreply, sizeof(struct bootpd_t)); - decode_rfc1533(BOOTP_DATA_ADDR->bootp_reply.bp_vend, -#ifdef NO_DHCP_SUPPORT - 0, BOOTP_VENDOR_LEN + MAX_BOOTP_EXTLEN, 1); -#else - 0, DHCP_OPT_LEN + MAX_BOOTP_EXTLEN, 1); -#endif /* NO_DHCP_SUPPORT */ - return(1); - } - -#ifdef DOWNLOAD_PROTO_TFTP - /* TFTP ? */ - if ((type == AWAIT_TFTP) && - (ntohs(udp->dest) == ival)) return(1); -#endif /* DOWNLOAD_PROTO_TFTP */ - -#ifdef DOWNLOAD_PROTO_NFS - /* RPC ? */ - rpc = (struct rpc_t *)&nic.packet[ETHER_HDR_SIZE]; - if ((type == AWAIT_RPC) && - (ntohs(udp->dest) == ival) && - (*(unsigned long *)ptr == ntohl(rpc->u.reply.id)) && - (ntohl(rpc->u.reply.type) == MSG_REPLY)) { - return (1); - } -#endif /* DOWNLOAD_PROTO_NFS */ - - } else { - /* Check for abort key only if the Rx queue is empty - - * as long as we have something to process, don't - * assume that something failed. It is unlikely that - * we have no processing time left between packets. */ - if (iskey() && (getchar() == ESC)) -#ifdef EMERGENCYDISKBOOT - exit(0); -#else - longjmp(jmp_bootmenu,1); -#endif - /* Do the timeout after at least a full queue walk. */ - if ((timeout == 0) || (currticks() > time)) { - break; - } - } - } - return(0); -} - -/************************************************************************** -DECODE_RFC1533 - Decodes RFC1533 header -**************************************************************************/ -int decode_rfc1533(p, block, len, eof) - register unsigned char *p; - int block, len, eof; -{ - static unsigned char *extdata = NULL, *extend = NULL; - unsigned char *extpath = NULL; - unsigned char *endp; - - if (block == 0) { -#ifdef IMAGE_MENU - memset(imagelist, 0, sizeof(imagelist)); - menudefault = useimagemenu = 0; - menutmo = -1; -#endif -#ifdef MOTD - memset(motd, 0, sizeof(motd)); -#endif - end_of_rfc1533 = NULL; - vendorext_isvalid = 0; - if (memcmp(p, rfc1533_cookie, 4)) - return(0); /* no RFC 1533 header found */ - p += 4; - endp = p + len; } - else { - if (block == 1) { - if (memcmp(p, rfc1533_cookie, 4)) - return(0); /* no RFC 1533 header found */ - p += 4; - len -= 4; } - if (extend + len <= (unsigned char *)&(BOOTP_DATA_ADDR->bootp_extension[MAX_BOOTP_EXTLEN])) { - memcpy(extend, p, len); - extend += len; - } else { - printf("Overflow in vendor data buffer! Aborting...\n"); - *extdata = RFC1533_END; - return(0); - } - p = extdata; endp = extend; - } - if (eof) { - while(p < endp) { - unsigned char c = *p; - if (c == RFC1533_PAD) {p++; continue;} - else if (c == RFC1533_END) { - end_of_rfc1533 = endp = p; continue; } - else if (c == RFC1533_NETMASK) {memcpy(&netmask, p+2, sizeof(in_addr));} - - else if (c == RFC1533_GATEWAY) { - /* This is a little simplistic, but it will - usually be sufficient. - Take only the first entry */ - if (TAG_LEN(p) >= sizeof(in_addr)) - memcpy(&arptable[ARP_GATEWAY].ipaddr, p+2, sizeof(in_addr)); - } - else if (c == RFC1533_EXTENSIONPATH) - extpath = p; -#ifndef NO_DHCP_SUPPORT - else if (c == RFC2132_MSG_TYPE) - { dhcp_reply=*(p+2); - } - else if (c == RFC2132_SRV_ID) - { - memcpy(&dhcp_server, p+2, sizeof(in_addr)); - } -#endif /* NO_DHCP_SUPPORT */ - else if (c == RFC1533_HOSTNAME) - { - hostname = p + 2; - hostnamelen = *(p + 1); - } - else if (c == RFC1533_VENDOR_MAGIC -#ifndef IMAGE_FREEBSD /* since FreeBSD uses tag 128 for swap definition */ - && TAG_LEN(p) >= 6 && - !memcmp(p+2,vendorext_magic,4) && - p[6] == RFC1533_VENDOR_MAJOR -#endif - ) - vendorext_isvalid++; -#ifdef IMAGE_FREEBSD - else if (c == RFC1533_VENDOR_HOWTO) { - freebsd_howto = ((p[2]*256+p[3])*256+p[4])*256+p[5]; - } -#endif -#ifdef IMAGE_MENU - else if (c == RFC1533_VENDOR_MNUOPTS) { - parse_menuopts(p+2, TAG_LEN(p)); - } - else if (c >= RFC1533_VENDOR_IMG && - c<RFC1533_VENDOR_IMG+RFC1533_VENDOR_NUMOFIMG){ - imagelist[c - RFC1533_VENDOR_IMG] = p; - useimagemenu++; - } -#endif -#ifdef MOTD - else if (c >= RFC1533_VENDOR_MOTD && - c < RFC1533_VENDOR_MOTD + - RFC1533_VENDOR_NUMOFMOTD) - motd[c - RFC1533_VENDOR_MOTD] = p; -#endif - else { -#if 0 - unsigned char *q; - printf("Unknown RFC1533-tag "); - for(q=p;q<p+2+TAG_LEN(p);q++) - printf("%x ",*q); - putchar('\n'); -#endif - } - p += TAG_LEN(p) + 2; - } - extdata = extend = endp; - if (block == 0 && extpath != NULL) { - char fname[64]; - memcpy(fname, extpath+2, TAG_LEN(extpath)); - fname[(int)TAG_LEN(extpath)] = '\000'; - printf("Loading BOOTP-extension file: %s\n",fname); - download(fname,decode_rfc1533); - } - } - return(-1); /* proceed with next block */ -} - -/************************************************************************** -IPCHKSUM - Checksum IP Header -**************************************************************************/ -unsigned short ipchksum(ip, len) - register unsigned short *ip; - register int len; -{ - unsigned long sum = 0; - len >>= 1; - while (len--) { - sum += *(ip++); - if (sum > 0xFFFF) - sum -= 0xFFFF; - } - return((~sum) & 0x0000FFFF); -} - -/************************************************************************** -RFC951_SLEEP - sleep for expotentially longer times -**************************************************************************/ -void rfc951_sleep(exp) - int exp; -{ - static long seed = 0; - long q; - unsigned long tmo; - -#ifdef BACKOFF_LIMIT - if (exp > BACKOFF_LIMIT) - exp = BACKOFF_LIMIT; -#endif - if (!seed) /* Initialize linear congruential generator */ - seed = currticks() + *(long *)&arptable[ARP_CLIENT].node - + ((short *)arptable[ARP_CLIENT].node)[2]; - /* simplified version of the LCG given in Bruce Scheier's - "Applied Cryptography" */ - q = seed/53668; - if ((seed = 40014*(seed-53668*q) - 12211*q) < 0) seed += 2147483563l; - /* compute mask */ - for (tmo = 63; tmo <= 60*TICKS_PER_SEC && --exp > 0; tmo = 2*tmo+1); - /* sleep */ - printf("<sleep>\n"); - - for (tmo = (tmo&seed)+currticks(); currticks() < tmo; ) - if (iskey() && (getchar() == ESC)) longjmp(jmp_bootmenu,1); - return; -} - -/************************************************************************** -CLEANUP_NET - shut down networking -**************************************************************************/ -void cleanup_net(void) -{ -#ifdef DOWNLOAD_PROTO_NFS - nfs_umountall(ARP_SERVER); -#endif - eth_disable(); - eth_reset(); -} - -/************************************************************************** -CLEANUP - shut down etherboot so that the OS may be called right away -**************************************************************************/ -void cleanup(void) -{ -#if defined(ANSIESC) && defined(CONSOLE_CRT) - ansi_reset(); -#endif -} - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ |