⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.c

📁 i386的bootloader源码grub
💻 C
📖 第 1 页 / 共 3 页
字号:
/* *  GRUB  --  GRand Unified Bootloader *  Copyright (C) 2000,2001,2002  Free Software Foundation, Inc. * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2 of the License, or *  (at your option) any later version. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * *  You should have received a copy of the GNU General Public License *  along with this program; if not, write to the Free Software *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *//* Based on "src/main.c" in etherboot-5.0.5.  *//**************************************************************************ETHERBOOT -  BOOTP/TFTP Bootstrap ProgramAuthor: 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 GRUB	1#include <etherboot.h>#include <nic.h>/* #define DEBUG	1 */struct arptable_t arptable[MAX_ARP];/* Set if the user pushes Control-C.  */int ip_abort = 0;/* Set if an ethernet card is probed and IP addresses are set.  */int network_ready = 0;struct rom_info rom;static int vendorext_isvalid;static unsigned long netmask;static struct bootpd_t bootp_data;static unsigned long xid;static unsigned char *end_of_rfc1533 = NULL;#ifndef	NO_DHCP_SUPPORT#endif /* NO_DHCP_SUPPORT *//* 銭th */static unsigned char vendorext_magic[] = {0xE4, 0x45, 0x74, 0x68};static const unsigned char broadcast[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};#ifdef	NO_DHCP_SUPPORTstatic unsigned char rfc1533_cookie[5] = {RFC1533_COOKIE, RFC1533_END};#else /* ! NO_DHCP_SUPPORT */static int dhcp_reply;static in_addr dhcp_server = {0L};static in_addr dhcp_addr = {0L};static unsigned char rfc1533_cookie[] = {RFC1533_COOKIE};static unsigned char rfc1533_end[] = {RFC1533_END};static const unsigned char dhcpdiscover[] ={  RFC2132_MSG_TYPE, 1, DHCPDISCOVER,	  RFC2132_MAX_SIZE,2,	/* request as much as we can */  ETH_MAX_MTU / 256, ETH_MAX_MTU % 256,  RFC2132_PARAM_LIST, 4, RFC1533_NETMASK, RFC1533_GATEWAY,  RFC1533_HOSTNAME, RFC1533_EXTENSIONPATH};static const unsigned 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 */  ETH_MAX_MTU / 256, ETH_MAX_MTU % 256,  /* request parameters */  RFC2132_PARAM_LIST,  /* 4 standard + 2 vendortags */  4 + 2,  /* Standard parameters */  RFC1533_NETMASK, RFC1533_GATEWAY,  RFC1533_HOSTNAME, RFC1533_EXTENSIONPATH,  /* Etherboot vendortags */  RFC1533_VENDOR_MAGIC,  RFC1533_VENDOR_CONFIGFILE,};#endif /* ! NO_DHCP_SUPPORT */static unsigned short ipchksum (unsigned short *ip, int len);static unsigned short udpchksum (struct iphdr *packet);voidprint_network_configuration (void){  if (! eth_probe ())    grub_printf ("No ethernet card found.\n");  else if (! network_ready)    grub_printf ("Not initialized yet.\n");  else    {      etherboot_printf ("Address: %@\n", arptable[ARP_CLIENT].ipaddr.s_addr);      etherboot_printf ("Netmask: %@\n", netmask);      etherboot_printf ("Server: %@\n", arptable[ARP_SERVER].ipaddr.s_addr);      etherboot_printf ("Gateway: %@\n", arptable[ARP_GATEWAY].ipaddr.s_addr);    }}/**************************************************************************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));}/* ifconfig - configure network interface.  */intifconfig (char *ip, char *sm, char *gw, char *svr){  in_addr tmp;    if (sm)     {      if (! inet_aton (sm, &tmp))	return 0;            netmask = tmp.s_addr;    }    if (ip)     {      if (! inet_aton (ip, &arptable[ARP_CLIENT].ipaddr)) 	return 0;            if (! netmask && ! sm) 	netmask = default_netmask ();    }    if (gw && ! inet_aton (gw, &arptable[ARP_GATEWAY].ipaddr))     return 0;  /* Clear out the ARP entry.  */  grub_memset (arptable[ARP_GATEWAY].node, 0, ETH_ALEN);    if (svr && ! inet_aton (svr, &arptable[ARP_SERVER].ipaddr))     return 0;  /* Likewise.  */  grub_memset (arptable[ARP_SERVER].node, 0, ETH_ALEN);    if (ip || sm)    {      if (IP_BROADCAST == (netmask | arptable[ARP_CLIENT].ipaddr.s_addr)	  || netmask == (netmask | arptable[ARP_CLIENT].ipaddr.s_addr)	  || ! netmask)	network_ready = 0;      else	network_ready = 1;    }    return 1;}/**************************************************************************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 *) ((unsigned 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;  udp->chksum = htons (udpchksum (ip));  if (udp->chksum == 0)    udp->chksum = 0xffff;    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)	{	  etherboot_printf ("%@ is not in my arp table!\n", destip);	  return 0;	}            for (i = 0; i < ETH_ALEN; i++)	if (arptable[arpentry].node[i])	  break;            if (i == ETH_ALEN)	{	  /* Need to do arp request.  */#ifdef DEBUG	  grub_printf ("arp request.\n");#endif	  arpreq.hwtype = htons (1);	  arpreq.protocol = htons (IP);	  arpreq.hwlen = ETH_ALEN;	  arpreq.protolen = 4;	  arpreq.opcode = htons (ARP_REQUEST);	  grub_memmove (arpreq.shwaddr, arptable[ARP_CLIENT].node,			ETH_ALEN);	  grub_memmove (arpreq.sipaddr, (char *) &arptable[ARP_CLIENT].ipaddr,			sizeof (in_addr));	  grub_memset (arpreq.thwaddr, 0, ETH_ALEN);	  grub_memmove (arpreq.tipaddr, (char *) &destip, sizeof (in_addr));	  	  for (retry = 1; retry <= MAX_ARP_RETRIES; retry++)	    {	      long timeout;	      	      eth_transmit (broadcast, ARP, sizeof (arpreq), &arpreq);	      timeout = rfc2131_sleep_interval (TIMEOUT, retry);	      	      if (await_reply (AWAIT_ARP, arpentry, arpreq.tipaddr, timeout))		goto xmit;	      if (ip_abort)		return 0;	    }	  	  return 0;	}          xmit:      eth_transmit (arptable[arpentry].node, IP, len, buf);    }    return 1;}/**************************************************************************TFTP - Download extended BOOTP data, or kernel image**************************************************************************/static inttftp (const char *name, int (*fnc) (unsigned char *, int, int, int)){  int retry = 0;  static unsigned short iport = 2000;  unsigned short oport = 0;  unsigned short len, block = 0, prevblock = 0;  int bcounter = 0;  struct tftp_t *tr;  struct tftpreq_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 = (grub_sprintf ((char *) tp.u.rrq, "%s%coctet%cblksize%c%d",		       name, 0, 0, 0, TFTP_MAX_PACKET)	 + sizeof (tp.ip) + sizeof (tp.udp) + sizeof (tp.opcode) + 1);  if (! udp_transmit (arptable[ARP_SERVER].ipaddr.s_addr, ++iport,		      TFTP_PORT, len, &tp))    return 0;    for (;;)    {      long timeout;      #ifdef CONGESTED      timeout = rfc2131_sleep_interval (block ? TFTP_REXMT : TIMEOUT, retry);#else      timeout = rfc2131_sleep_interval (TIMEOUT, retry);#endif      if (! await_reply (AWAIT_TFTP, iport, NULL, timeout))	{	  if (! block && retry++ < MAX_TFTP_RETRIES)	    {	      /* Maybe initial request was lost.  */	      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	      grub_printf ("<REXMT>\n");#endif	      udp_transmit (arptable[ARP_SERVER].ipaddr.s_addr,			    iport, oport,			    TFTP_MIN_PACKET, &tp);	      continue;	    }#endif	  /* Timeout.  */	  break;	}            tr = (struct tftp_t *) &nic.packet[ETH_HLEN];      if (tr->opcode == ntohs (TFTP_ERROR))	{	  grub_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;	  	  /* Shouldn't happen.  */	  if (prevblock)	    /* Ignore it.  */	    continue;	  	  len = ntohs (tr->udp.len) - sizeof (struct udphdr) - 2;	  if (len > TFTP_MAX_PACKET)	    goto noak;	  	  e = p + len;	  while (*p != '\000' && p < e)	    {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -