15b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/*
25b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  GRUB  --  GRand Unified Bootloader
35b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  Copyright (C) 2000,2001,2002,2004  Free Software Foundation, Inc.
45b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
55b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  This program is free software; you can redistribute it and/or modify
65b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  it under the terms of the GNU General Public License as published by
75b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  the Free Software Foundation; either version 2 of the License, or
85b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  (at your option) any later version.
95b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  This program is distributed in the hope that it will be useful,
115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  but WITHOUT ANY WARRANTY; without even the implied warranty of
125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  GNU General Public License for more details.
145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  You should have received a copy of the GNU General Public License
165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  along with this program; if not, write to the Free Software
175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project */
195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* Based on "src/main.c" in etherboot-4.5.8.  */
215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/**************************************************************************
225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source ProjectETHERBOOT -  BOOTP/TFTP Bootstrap Program
235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source ProjectAuthor: Martin Renters
255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  Date: Dec/93
265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project**************************************************************************/
285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* #define TFTP_DEBUG	1 */
305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#include <filesys.h>
325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define GRUB	1
345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#include <etherboot.h>
355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#include <nic.h>
365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic int retry;
385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic unsigned short iport = 2000;
395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic unsigned short oport;
405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic unsigned short block, prevblock;
415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic int bcounter;
425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic struct tftp_t tp, saved_tp;
435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic int packetsize;
445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic int buf_eof, buf_read;
455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic int saved_filepos;
465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic unsigned short len, saved_len;
475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic char *buf;
485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* Fill the buffer by receiving the data via the TFTP protocol.  */
505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic int
515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectbuf_fill (int abort)
525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef TFTP_DEBUG
545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  grub_printf ("buf_fill (%d)\n", abort);
555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  while (! buf_eof && (buf_read + packetsize <= FSYS_BUFLEN))
585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    {
595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      struct tftp_t *tr;
605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      long timeout;
615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef CONGESTED
635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      timeout = rfc2131_sleep_interval (block ? TFTP_REXMT : TIMEOUT, retry);
645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#else
655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      timeout = rfc2131_sleep_interval (TIMEOUT, retry);
665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      if (! await_reply (AWAIT_TFTP, iport, NULL, timeout))
695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{
705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  if (ip_abort)
715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    return 0;
725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  if (! block && retry++ < MAX_TFTP_RETRIES)
745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    {
755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      /* Maybe initial request was lost.  */
765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef TFTP_DEBUG
775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      grub_printf ("Maybe initial request was lost.\n");
785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      if (! udp_transmit (arptable[ARP_SERVER].ipaddr.s_addr,
805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project				  ++iport, TFTP_PORT, len, &tp))
815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		return 0;
825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      continue;
845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    }
855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef CONGESTED
875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  if (block && ((retry += TFTP_REXMT) < TFTP_TIMEOUT))
885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    {
895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      /* We resend our last ack.  */
905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project# ifdef TFTP_DEBUG
915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      grub_printf ("<REXMT>\n");
925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project# endif
935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      udp_transmit (arptable[ARP_SERVER].ipaddr.s_addr,
945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			    iport, oport,
955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			    TFTP_MIN_PACKET, &tp);
965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      continue;
975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    }
985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  /* Timeout.  */
1005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  return 0;
1015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
1025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      tr = (struct tftp_t *) &nic.packet[ETH_HLEN];
1045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      if (tr->opcode == ntohs (TFTP_ERROR))
1055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{
1065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  grub_printf ("TFTP error %d (%s)\n",
1075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		       ntohs (tr->u.err.errcode),
1085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		       tr->u.err.errmsg);
1095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  return 0;
1105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
1115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      if (tr->opcode == ntohs (TFTP_OACK))
1135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{
1145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  char *p = tr->u.oack.data, *e;
1155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef TFTP_DEBUG
1175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  grub_printf ("OACK ");
1185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
1195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  /* Shouldn't happen.  */
1205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  if (prevblock)
1215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    {
1225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      /* Ignore it.  */
1235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      grub_printf ("%s:%d: warning: PREVBLOCK != 0 (0x%x)\n",
1245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			   __FILE__, __LINE__, prevblock);
1255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      continue;
1265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    }
1275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  len = ntohs (tr->udp.len) - sizeof (struct udphdr) - 2;
1295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  if (len > TFTP_MAX_PACKET)
1305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    goto noak;
1315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  e = p + len;
1335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  while (*p != '\000' && p < e)
1345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    {
1355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      if (! grub_strcmp ("blksize", p))
1365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		{
1375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		  p += 8;
1385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		  if ((packetsize = getdec (&p)) < TFTP_DEFAULTSIZE_PACKET)
1395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		    goto noak;
1405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef TFTP_DEBUG
1415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		  grub_printf ("blksize = %d\n", packetsize);
1425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
1435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		}
1445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      else if (! grub_strcmp ("tsize", p))
1455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		{
1465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		  p += 6;
1475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		  if ((filemax = getdec (&p)) < 0)
1485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		    {
1495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		      filemax = -1;
1505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		      goto noak;
1515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		    }
1525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef TFTP_DEBUG
1535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		  grub_printf ("tsize = %d\n", filemax);
1545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
1555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		}
1565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      else
1575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		{
1585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		noak:
1595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef TFTP_DEBUG
1605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		  grub_printf ("NOAK\n");
1615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
1625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		  tp.opcode = htons (TFTP_ERROR);
1635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		  tp.u.err.errcode = 8;
1645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		  len = (grub_sprintf ((char *) tp.u.err.errmsg,
1655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project				       "RFC1782 error")
1665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			 + sizeof (tp.ip) + sizeof (tp.udp)
1675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			 + sizeof (tp.opcode) + sizeof (tp.u.err.errcode)
1685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			 + 1);
1695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		  udp_transmit (arptable[ARP_SERVER].ipaddr.s_addr,
1705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project				iport, ntohs (tr->udp.src),
1715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project				len, &tp);
1725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		  return 0;
1735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		}
1745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      while (p < e && *p)
1765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		p++;
1775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      if (p < e)
1795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		p++;
1805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    }
1815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  if (p > e)
1835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    goto noak;
1845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  /* This ensures that the packet does not get processed as
1865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	     data!  */
1875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  block = tp.u.ack.block = 0;
1885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
1895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      else if (tr->opcode == ntohs (TFTP_DATA))
1905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{
1915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef TFTP_DEBUG
1925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  grub_printf ("DATA ");
1935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
1945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  len = ntohs (tr->udp.len) - sizeof (struct udphdr) - 4;
1955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  /* Shouldn't happen.  */
1975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  if (len > packetsize)
1985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    {
1995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      /* Ignore it.  */
2005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      grub_printf ("%s:%d: warning: LEN > PACKETSIZE (0x%x > 0x%x)\n",
2015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			   __FILE__, __LINE__, len, packetsize);
2025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      continue;
2035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    }
2045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  block = ntohs (tp.u.ack.block = tr->u.data.block);
2065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
2075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      else
2085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	/* Neither TFTP_OACK nor TFTP_DATA.  */
2095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	break;
2105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      if ((block || bcounter) && (block != prevblock + (unsigned short) 1))
2125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	/* Block order should be continuous */
2135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	tp.u.ack.block = htons (block = prevblock);
2145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      /* Should be continuous.  */
2165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      tp.opcode = abort ? htons (TFTP_ERROR) : htons (TFTP_ACK);
2175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      oport = ntohs (tr->udp.src);
2185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef TFTP_DEBUG
2205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      grub_printf ("ACK\n");
2215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
2225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      /* Ack.  */
2235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      udp_transmit (arptable[ARP_SERVER].ipaddr.s_addr, iport,
2245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		    oport, TFTP_MIN_PACKET, &tp);
2255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      if (abort)
2275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{
2285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  buf_eof = 1;
2295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  break;
2305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
2315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      /* Retransmission or OACK.  */
2335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      if ((unsigned short) (block - prevblock) != 1)
2345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	/* Don't process.  */
2355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	continue;
2365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      prevblock = block;
2385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      /* Is it the right place to zero the timer?  */
2395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      retry = 0;
2405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      /* In GRUB, this variable doesn't play any important role at all,
2425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	 but use it for consistency with Etherboot.  */
2435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      bcounter++;
2445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      /* Copy the downloaded data to the buffer.  */
2465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      grub_memmove (buf + buf_read, tr->u.data.download, len);
2475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      buf_read += len;
2485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      /* End of data.  */
2505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      if (len < packetsize)
2515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	buf_eof = 1;
2525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
2535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  return 1;
2555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
2565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* Send the RRQ whose length is LEN.  */
2585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic int
2595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectsend_rrq (void)
2605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
2615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  /* Initialize some variables.  */
2625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  retry = 0;
2635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  block = 0;
2645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  prevblock = 0;
2655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  packetsize = TFTP_DEFAULTSIZE_PACKET;
2665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  bcounter = 0;
2675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  buf = (char *) FSYS_BUF;
2695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  buf_eof = 0;
2705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  buf_read = 0;
2715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  saved_filepos = 0;
2725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  /* Clear out the Rx queue first.  It contains nothing of interest,
2745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   * except possibly ARP requests from the DHCP/TFTP server.  We use
2755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   * polling throughout Etherboot, so some time may have passed since we
2765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   * last polled the receive queue, which may now be filled with
2775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   * broadcast packets.  This will cause the reply to the packets we are
2785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   * about to send to be lost immediately.  Not very clever.  */
2795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  await_reply (AWAIT_QDRAIN, 0, NULL, 0);
2805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef TFTP_DEBUG
2825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  grub_printf ("send_rrq ()\n");
2835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  {
2845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    int i;
2855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    char *p;
2865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    for (i = 0, p = (char *) &tp; i < len; i++)
2885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      if (p[i] >= ' ' && p[i] <= '~')
2895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	grub_putchar (p[i]);
2905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      else
2915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	grub_printf ("\\%x", (unsigned) p[i]);
2925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    grub_putchar ('\n');
2945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  }
2955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
2965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  /* Send the packet.  */
2975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  return udp_transmit (arptable[ARP_SERVER].ipaddr.s_addr, ++iport,
2985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		       TFTP_PORT, len, &tp);
2995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
3005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* Mount the network drive. If the drive is ready, return one, otherwise
3025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   return zero.  */
3035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectint
3045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projecttftp_mount (void)
3055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
3065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  /* Check if the current drive is the network drive.  */
3075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  if (current_drive != NETWORK_DRIVE)
3085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    return 0;
3095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  /* If the drive is not initialized yet, abort.  */
3115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  if (! network_ready)
3125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    return 0;
3135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  return 1;
3155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
3165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* Read up to SIZE bytes, returned in ADDR.  */
3185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectint
3195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projecttftp_read (char *addr, int size)
3205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
3215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  /* How many bytes is read?  */
3225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  int ret = 0;
3235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef TFTP_DEBUG
3255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  grub_printf ("tftp_read (0x%x, %d)\n", (int) addr, size);
3265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
3275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  if (filepos < saved_filepos)
3295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    {
3305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      /* Uggh.. FILEPOS has been moved backwards. So reopen the file.  */
3315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      buf_read = 0;
3325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      buf_fill (1);
3335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      grub_memmove ((char *) &tp, (char *) &saved_tp, saved_len);
3345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      len = saved_len;
3355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef TFTP_DEBUG
3365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      {
3375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	int i;
3385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	grub_printf ("opcode = 0x%x, rrq = ", (unsigned long) tp.opcode);
3395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	for (i = 0; i < TFTP_DEFAULTSIZE_PACKET; i++)
3405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  {
3415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    if (tp.u.rrq[i] >= ' ' && tp.u.rrq[i] <= '~')
3425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      grub_putchar (tp.u.rrq[i]);
3435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    else
3445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      grub_putchar ('*');
3455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  }
3465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	grub_putchar ('\n');
3475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      }
3485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
3495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      if (! send_rrq ())
3515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{
3525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  errnum = ERR_WRITE;
3535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  return 0;
3545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
3555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
3565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  while (size > 0)
3585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    {
3595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      int amt = buf_read + saved_filepos - filepos;
3605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      /* If the length that can be copied from the buffer is over the
3625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	 requested size, cut it down.  */
3635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      if (amt > size)
3645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	amt = size;
3655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      if (amt > 0)
3675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{
3685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  /* Copy the buffer to the supplied memory space.  */
3695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  grub_memmove (addr, buf + filepos - saved_filepos, amt);
3705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  size -= amt;
3715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  addr += amt;
3725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  filepos += amt;
3735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  ret += amt;
3745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  /* If the size of the empty space becomes small, move the unused
3765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	     data forwards.  */
3775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  if (filepos - saved_filepos > FSYS_BUFLEN / 2)
3785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    {
3795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      grub_memmove (buf, buf + FSYS_BUFLEN / 2, FSYS_BUFLEN / 2);
3805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      buf_read -= FSYS_BUFLEN / 2;
3815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      saved_filepos += FSYS_BUFLEN / 2;
3825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    }
3835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
3845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      else
3855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{
3865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  /* Skip the whole buffer.  */
3875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  saved_filepos += buf_read;
3885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  buf_read = 0;
3895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
3905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      /* Read the data.  */
3925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      if (size > 0 && ! buf_fill (0))
3935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{
3945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  errnum = ERR_READ;
3955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  return 0;
3965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
3975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      /* Sanity check.  */
3995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      if (size > 0 && buf_read == 0)
4005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{
4015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  errnum = ERR_READ;
4025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  return 0;
4035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
4045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
4055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  return ret;
4075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
4085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* Check if the file DIRNAME really exists. Get the size and save it in
4105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   FILEMAX.  */
4115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectint
4125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projecttftp_dir (char *dirname)
4135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
4145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  int ch;
4155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef TFTP_DEBUG
4175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  grub_printf ("tftp_dir (%s)\n", dirname);
4185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
4195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  /* In TFTP, there is no way to know what files exist.  */
4215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  if (print_possibilities)
4225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    return 1;
4235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  /* Don't know the size yet.  */
4255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  filemax = -1;
4265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project reopen:
4285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  /* Construct the TFTP request packet.  */
4295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  tp.opcode = htons (TFTP_RRQ);
4305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  /* Terminate the filename.  */
4315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  ch = nul_terminate (dirname);
4325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  /* Make the request string (octet, blksize and tsize).  */
4335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  len = (grub_sprintf ((char *) tp.u.rrq,
4345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		       "%s%coctet%cblksize%c%d%ctsize%c0",
4355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		       dirname, 0, 0, 0, TFTP_MAX_PACKET, 0, 0)
4365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	 + sizeof (tp.ip) + sizeof (tp.udp) + sizeof (tp.opcode) + 1);
4375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  /* Restore the original DIRNAME.  */
4385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  dirname[grub_strlen (dirname)] = ch;
4395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  /* Save the TFTP packet so that we can reopen the file later.  */
4405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  grub_memmove ((char *) &saved_tp, (char *) &tp, len);
4415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  saved_len = len;
4425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  if (! send_rrq ())
4435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    {
4445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      errnum = ERR_WRITE;
4455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      return 0;
4465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
4475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  /* Read the data.  */
4495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  if (! buf_fill (0))
4505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    {
4515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      errnum = ERR_FILE_NOT_FOUND;
4525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      return 0;
4535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
4545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  if (filemax == -1)
4565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    {
4575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      /* The server doesn't support the "tsize" option, so we must read
4585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	 the file twice...  */
4595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      /* Zero the size of the file.  */
4615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      filemax = 0;
4625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      do
4635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{
4645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  /* Add the length of the downloaded data.  */
4655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  filemax += buf_read;
4665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  /* Reset the offset. Just discard the contents of the buffer.  */
4675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  buf_read = 0;
4685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  /* Read the data.  */
4695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  if (! buf_fill (0))
4705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    {
4715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      errnum = ERR_READ;
4725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      return 0;
4735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    }
4745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
4755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      while (! buf_eof);
4765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      /* Maybe a few amounts of data remains.  */
4785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      filemax += buf_read;
4795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      /* Retry the open instruction.  */
4815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      goto reopen;
4825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
4835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  return 1;
4855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
4865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* Close the file.  */
4885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectvoid
4895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projecttftp_close (void)
4905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
4915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef TFTP_DEBUG
4925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  grub_printf ("tftp_close ()\n");
4935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
4945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  buf_read = 0;
4965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  buf_fill (1);
4975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
498