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