Main Page   Modules   Alphabetical List   Data Structures   File List   Data Fields   Related Pages  

C:/proj/src/ethernut/nut/eboot/tftp.c

00001 /*
00002  * Copyright (C) 2002 by egnite Software GmbH. All rights reserved.
00003  *
00004  * Redistribution and use in source and binary forms, with or without
00005  * modification, are permitted provided that the following conditions
00006  * are met:
00007  *
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. All advertising materials mentioning features or use of this
00014  *    software must display the following acknowledgement:
00015  *
00016  *    This product includes software developed by egnite Software GmbH
00017  *    and its contributors.
00018  *
00019  * THIS SOFTWARE IS PROVIDED BY EGNITE SOFTWARE GMBH AND CONTRIBUTORS
00020  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00021  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00022  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL EGNITE
00023  * SOFTWARE GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00024  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00025  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
00026  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
00027  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00028  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
00029  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00030  * SUCH DAMAGE.
00031  *
00032  * For additional information see http://www.ethernut.de/
00033  */
00034 
00035 /*
00036  * $Log: tftp.c,v $
00037  * Revision 1.1  2002/08/01 17:34:30  harald
00038  * First check in
00039  *
00040  */
00041 
00042 #include <io.h>
00043 #include <string.h>
00044 
00045 #include "flash.h"
00046 #include "eboot.h"
00047 #include "tftp.h"
00048 
00049 /*!
00050  * \addtogroup xgTftp
00051  */
00052 /*@{*/
00053 
00054 /*!
00055  * \brief Erase and program a page in the flash ROM.
00056  *
00057  * \param page The page number to program, 0..479.
00058  * \param data Pointer to the new page contents.
00059  * \param len  Number of bytes to program. If this is
00060  *             less than 256, then the remaining bytes
00061  *             will be filled with 0xFF.
00062  */
00063 static void FlashPage(u_short page, void *data, u_short len)
00064 {
00065     u_short i;
00066     u_short *wp = data;
00067 
00068     if(len > 256)
00069         len = 256;
00070 
00071     if(page >= 256) {
00072         if(page >= 480)
00073             return;
00074         outp(1, RAMPZ);
00075     }
00076     else
00077         outp(0, RAMPZ);
00078     page <<= 8;
00079 
00080     SpmCommand(page, (1 << PGERS) | (1 << SPMEN));
00081     SpmCommand(0, (1 << RWWSRE) | (1 << SPMEN));
00082 
00083     for(i = 0; i < len; i += 2, wp++)
00084         SpmBufferFill(i, *wp);
00085     for(; i < 256; i += 2)
00086         SpmBufferFill(i, 0xFFFF);
00087 
00088     SpmCommand(page, (1 << PGWRT) | (1 << SPMEN)); 
00089     SpmCommand(0, (1 << RWWSRE) | (1 << SPMEN));               
00090 }
00091 
00092 /*!
00093  * \brief Set up a TFTP header for a file request.
00094  *
00095  * \param th      Points to the TFTP header structure.
00096  * \param request Type of the request, either TFTP_RRQ or TFTP_WRQ.
00097  * \param name    Name of the files.
00098  * \param mode    Transfer mode.
00099  */
00100 static int MakeRequest(TFTPHDR *th, u_short request, u_char *name, u_char *mode)
00101 {
00102     u_char *cp;
00103 
00104     th->th_opcode = htons(request);
00105     cp = th->th_u.tu_stuff;
00106     while(*name)
00107         *cp++ = *name++;
00108     *cp++ = 0;
00109     while(*mode)
00110         *cp++ = *mode++;
00111     *cp++ = 0;
00112     return (u_short)cp - (u_short)th;
00113 }
00114 
00115 /*!
00116  * \brief Download a file from a TFTP server and burn it into the flash ROM.
00117  *
00118  * \return 0 on success, -1 otherwise.
00119  */
00120 int TftpRecv(void)
00121 {
00122     u_char retry;
00123     int rlen = 0;
00124     int slen;
00125     u_short sport = 1024;
00126     u_short tport = 69;
00127     u_short block = 0;
00128     
00129     /*
00130      * Prepare the transmit buffer for a file request.
00131      */
00132     slen = MakeRequest(&sframe.u.tftp, TFTP_RRQ, bootfile, "octet");
00133     
00134     /*
00135      * Lopp until we receive a packet with less than 512 bytes of data.
00136      */
00137     do {
00138         
00139         /*
00140          * Send file request or acknowledge and receive
00141          * a data block.
00142          */
00143         for(retry = 0; retry < 3; retry++) {
00144             if(UdpOutput(server_ip, tport, sport, slen) >= 0) {
00145                 if((rlen = UdpInput(sport, 5000)) >= 4)
00146                     break;
00147             }
00148         }
00149         
00150         /*
00151          * Can't reach the TFTP server or got a malformed
00152          * repsonse.
00153          */
00154         if(rlen < 4)
00155             return -1;
00156         
00157         
00158        /*
00159         * Accept data blocks only. Anything else will stop
00160         * the transfer with an error.
00161         */
00162         if(ntohs(rframe.u.tftp.th_opcode) != TFTP_DATA) 
00163             return -1;
00164         
00165        /*
00166         * If this was the first block we received, prepare
00167         * the send buffer for sending ACKs.
00168         */
00169         if(block == 0) {
00170             tport = ntohs(rframe.udp_hdr.uh_sport);
00171             sframe.u.tftp.th_opcode = htons(TFTP_ACK);
00172             slen = 4;
00173         }
00174         
00175         /*
00176          * If this block is out of sequence, we ignore it.
00177          * However, if we missed the first block, return
00178          * with an error.
00179          */
00180         if(ntohs(rframe.u.tftp.th_u.tu_block) != block + 1) {
00181             if(block == 0)
00182                 return -1;
00183             continue;
00184         }
00185         
00186         /*
00187          * Burn the received data into the flash ROM.
00188          */
00189         if(rlen > 4) {
00190             FlashPage(block << 1, rframe.u.tftp.th_data, rlen - 4);
00191             if(rlen > 260)
00192                 FlashPage((block << 1) + 1, &rframe.u.tftp.th_data[256], rlen - 260);
00193         }
00194         
00195         /*
00196          * Update our block counter.
00197          */
00198         block++;
00199         sframe.u.tftp.th_u.tu_block = htons(block);
00200         
00201     } while(rlen >= 516);
00202     
00203     /*
00204      * Send the last ACK.
00205      */
00206     UdpOutput(server_ip, tport, sport, slen);
00207 
00208     return 0;
00209 }
00210 
00211 /*@}*/

© 2002 by egnite Software GmbH - visit http://www.ethernut.de/