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

📄 main.c

📁 i386的bootloader源码grub
💻 C
📖 第 1 页 / 共 3 页
字号:
	      if (! grub_strcmp ("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 = (grub_sprintf ((char *) tp.u.err.errmsg,				       "RFC1782 error")			 + sizeof (tp.ip) + sizeof (tp.udp)			 + sizeof (tp.opcode) + sizeof (tp.u.err.errcode)			 + 1);		  udp_transmit (arptable[ARP_SERVER].ipaddr.s_addr,				iport, ntohs (tr->udp.src),				len, &tp);		  return 0;		}	    }	  	  if (p > e)	    goto noak;	  	  /* This ensures that the packet does not get processed as data!  */	  block = tp.u.ack.block = 0; 	}      else if (tr->opcode == ntohs (TFTP_DATA))	{	  len = ntohs (tr->udp.len) - sizeof (struct udphdr) - 4;	  /* Shouldn't happen.  */	  if (len > packetsize)	    /* Ignore it.  */	    continue;	  	  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);            /* Should be continuous.  */      tp.opcode = htons (TFTP_ACK);      oport = ntohs (tr->udp.src);      /* Ack.  */      udp_transmit (arptable[ARP_SERVER].ipaddr.s_addr, iport,		    oport, TFTP_MIN_PACKET, &tp);            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;      /* Is it the right place to zero the timer?  */      retry = 0;            if ((rc = fnc (tr->u.data.download,		     ++bcounter, len, len < packetsize)) >= 0)	return rc;      /* End of data.  */      if (len < packetsize)           	return 1;    }    return 0;}/**************************************************************************RARP - Get my IP address and load information**************************************************************************/int rarp (void){  int retry;  /* arp and rarp requests share the same packet structure.  */  struct arprequest rarpreq;  /* Make sure that an ethernet is probed.  */  if (! eth_probe ())    return 0;  /* Clear the ready flag.  */  network_ready = 0;    grub_memset (&rarpreq, 0, sizeof (rarpreq));  rarpreq.hwtype = htons (1);  rarpreq.protocol = htons (IP);  rarpreq.hwlen = ETH_ALEN;  rarpreq.protolen = 4;  rarpreq.opcode = htons (RARP_REQUEST);  grub_memmove ((char *) &rarpreq.shwaddr, arptable[ARP_CLIENT].node,		ETH_ALEN);  /* sipaddr is already zeroed out */  grub_memmove ((char *) &rarpreq.thwaddr, arptable[ARP_CLIENT].node,		ETH_ALEN);  /* tipaddr is already zeroed out */  for (retry = 0; retry < MAX_ARP_RETRIES; ++retry)    {      long timeout;            eth_transmit (broadcast, RARP, sizeof (rarpreq), &rarpreq);      timeout = rfc2131_sleep_interval (TIMEOUT, retry);      if (await_reply (AWAIT_RARP, 0, rarpreq.shwaddr, timeout))	break;      if (ip_abort)	return 0;    }  if (retry < MAX_ARP_RETRIES)    {      network_ready = 1;      return 1;    }  return 0;}/**************************************************************************BOOTP - Get my IP address and load information**************************************************************************/int bootp (void){  int retry;#ifndef	NO_DHCP_SUPPORT  int reqretry;#endif /* ! NO_DHCP_SUPPORT */  struct bootpip_t ip;  unsigned long starttime;  /* Make sure that an ethernet is probed.  */  if (! eth_probe ())    return 0;  /* Clear the ready flag.  */  network_ready = 0;#ifdef DEBUG  grub_printf ("network is ready.\n");#endif    grub_memset (&ip, 0, sizeof (struct bootpip_t));  ip.bp.bp_op = BOOTP_REQUEST;  ip.bp.bp_htype = 1;  ip.bp.bp_hlen = ETH_ALEN;  starttime = currticks ();  /* Use lower 32 bits of node address, more likely to be     distinct than the time since booting */  grub_memmove (&xid, &arptable[ARP_CLIENT].node[2], sizeof(xid));  ip.bp.bp_xid = xid += htonl (starttime);  grub_memmove (ip.bp.bp_hwaddr, arptable[ARP_CLIENT].node, ETH_ALEN);#ifdef DEBUG  etherboot_printf ("bp_op = %d\n", ip.bp.bp_op);  etherboot_printf ("bp_htype = %d\n", ip.bp.bp_htype);  etherboot_printf ("bp_hlen = %d\n", ip.bp.bp_hlen);  etherboot_printf ("bp_xid = %d\n", ip.bp.bp_xid);  etherboot_printf ("bp_hwaddr = %!\n", ip.bp.bp_hwaddr);  etherboot_printf ("bp_hops = %d\n", (int) ip.bp.bp_hops);  etherboot_printf ("bp_secs = %d\n", (int) ip.bp.bp_hwaddr);#endif  #ifdef	NO_DHCP_SUPPORT  /* Request RFC-style options.  */  grub_memmove (ip.bp.bp_vend, rfc1533_cookie, 5);#else  /* Request RFC-style options.  */  grub_memmove (ip.bp.bp_vend, rfc1533_cookie, sizeof rfc1533_cookie);  grub_memmove (ip.bp.bp_vend + sizeof rfc1533_cookie, dhcpdiscover,		sizeof dhcpdiscover);  grub_memmove (ip.bp.bp_vend + sizeof rfc1533_cookie + sizeof dhcpdiscover,		rfc1533_end, sizeof rfc1533_end);#endif /* ! NO_DHCP_SUPPORT */  for (retry = 0; retry < MAX_BOOTP_RETRIES;)    {      long timeout;#ifdef DEBUG      grub_printf ("retry = %d\n", retry);#endif            /* 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 bootpip_t), &ip);      timeout = rfc2131_sleep_interval (TIMEOUT, retry++);#ifdef NO_DHCP_SUPPORT      if (await_reply (AWAIT_BOOTP, 0, NULL, timeout))	{	  network_ready = 1;	  return 1;	}#else /* ! NO_DHCP_SUPPORT */      if (await_reply (AWAIT_BOOTP, 0, NULL, timeout))	{	  if (dhcp_reply != DHCPOFFER)	    {	      network_ready = 1;	      return 1;	    }	  dhcp_reply = 0;#ifdef DEBUG  etherboot_printf ("bp_op = %d\n", (int) ip.bp.bp_op);  etherboot_printf ("bp_htype = %d\n", (int) ip.bp.bp_htype);  etherboot_printf ("bp_hlen = %d\n", (int) ip.bp.bp_hlen);  etherboot_printf ("bp_xid = %d\n", (int) ip.bp.bp_xid);  etherboot_printf ("bp_hwaddr = %!\n", ip.bp.bp_hwaddr);  etherboot_printf ("bp_hops = %d\n", (int) ip.bp.bp_hops);  etherboot_printf ("bp_secs = %d\n", (int) ip.bp.bp_hwaddr);#endif	  grub_memmove (ip.bp.bp_vend, rfc1533_cookie, sizeof rfc1533_cookie);	  grub_memmove (ip.bp.bp_vend + sizeof rfc1533_cookie,			dhcprequest, sizeof dhcprequest);	  grub_memmove (ip.bp.bp_vend + sizeof rfc1533_cookie			+ sizeof dhcprequest,			rfc1533_end, sizeof rfc1533_end);	  grub_memmove (ip.bp.bp_vend + 9, (char *) &dhcp_server,			sizeof (in_addr));	  grub_memmove (ip.bp.bp_vend + 15, (char *) &dhcp_addr,			sizeof (in_addr));#ifdef DEBUG	  grub_printf ("errnum = %d\n", errnum);#endif	  for (reqretry = 0; reqretry < MAX_BOOTP_RETRIES;)	    {	      int ret;#ifdef DEBUG	      grub_printf ("reqretry = %d\n", reqretry);#endif	      	      ret = udp_transmit (IP_BROADCAST, BOOTP_CLIENT, BOOTP_SERVER,				  sizeof (struct bootpip_t), &ip);	      if (! ret)		grub_printf ("udp_transmit failed.\n");	      	      dhcp_reply = 0;	      timeout = rfc2131_sleep_interval (TIMEOUT, reqretry++);	      if (await_reply (AWAIT_BOOTP, 0, NULL, timeout))		if (dhcp_reply == DHCPACK)		  {		    network_ready = 1;		    return 1;		  }#ifdef DEBUG	      grub_printf ("dhcp_reply = %d\n", dhcp_reply);#endif	      	      if (ip_abort)		return 0;	    }	}#endif /* ! NO_DHCP_SUPPORT */            if (ip_abort)	return 0;            ip.bp.bp_secs = htons ((currticks () - starttime) / TICKS_PER_SEC);    }  /* Timeout.  */  return 0;}/**************************************************************************UDPCHKSUM - Checksum UDP Packet (one of the rare cases when assembly is            actually simpler...) RETURNS: checksum, 0 on checksum error. This          allows for using the same routine for RX and TX summing:          RX  if (packet->udp.chksum && udpchksum(packet))                  error("checksum error");          TX  packet->udp.chksum=0;              if (0==(packet->udp.chksum=udpchksum(packet)))                  packet->upd.chksum=0xffff;**************************************************************************/static inline voiddosum (unsigned short *start, unsigned int len, unsigned short *sum){  __asm__ __volatile__    ("clc\n"     "1:\tlodsw\n\t"     "xchg %%al,%%ah\n\t"	/* convert to host byte order */     "adcw %%ax,%0\n\t"		/* add carry of previous iteration */     "loop 1b\n\t"     "adcw $0,%0"		/* add carry of last iteration */     : "=b" (*sum), "=S"(start), "=c"(len)     : "0"(*sum), "1"(start), "2"(len)     : "ax", "cc"     );}/* UDP sum: * proto, src_ip, dst_ip, udp_dport, udp_sport, 2*udp_len, payload */static unsigned shortudpchksum (struct iphdr *packet){  int len = ntohs (packet->len);  unsigned short rval;    /* add udplength + protocol number */  rval = (len - sizeof (struct iphdr)) + IP_UDP;    /* pad to an even number of bytes */  if (len % 2) {    ((char *) packet)[len++] = 0;  }    /* sum over src/dst ipaddr + udp packet */  len -= (char *) &packet->src - (char *) packet;  dosum ((unsigned short *) &packet->src, len >> 1, &rval);    /* take one's complement */  return ~rval;}/**************************************************************************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;  unsigned short ptype;  unsigned int protohdrlen = (ETH_HLEN + sizeof (struct iphdr)			      + sizeof (struct udphdr));  /* Clear the abort flag.  */  ip_abort = 0;    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 >= ETH_HLEN)	    {	      ptype = (((unsigned short) nic.packet[12]) << 8		       | ((unsigned short) nic.packet[13]));	    }	  else	    /* What else could we do with it?  */	    continue;	  	  if (nic.packetlen >= ETH_HLEN + sizeof (struct arprequest)	      && ptype == ARP)	    {	      unsigned long tmp;	      arpreply = (struct arprequest *) &nic.packet[ETH_HLEN];	      	      if (arpreply->opcode == htons (ARP_REPLY)		  && ! grub_memcmp (arpreply->sipaddr, ptr, sizeof (in_addr))		  && type == AWAIT_ARP)

⌨️ 快捷键说明

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