OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [bootloaders/] [orpmon/] [services/] [tftp.c] - Blame information for rev 307

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 marcus.erl
/*
2
 *      Copyright 1994, 1995, 2000 Neil Russell.
3
 *      (See License)
4
 *      Copyright 2000, 2001 DENX Software Engineering, Wolfgang Denk, wd@denx.de
5
 */
6
 
7
#include "common.h"
8
#include "support.h"
9
#include "net.h"
10
#include "tftp.h"
11
#include "bootp.h"
12
 
13
 
14
#define WELL_KNOWN_PORT 69              /* Well known TFTP port #               */
15
#define TIMEOUT         2               /* Seconds to timeout for a lost pkt    */
16
#define TIMEOUT_COUNT   10              /* # of timeouts before giving up       */
17
                                        /* (for checking the image size)        */
18
#define HASHES_PER_LINE 65              /* Number of "loading" hashes per line  */
19
 
20
/*
21
 *      TFTP operations.
22
 */
23
#define TFTP_RRQ        1
24
#define TFTP_WRQ        2
25
#define TFTP_DATA       3
26
#define TFTP_ACK        4
27
#define TFTP_ERROR      5
28
 
29
 
30
static int      TftpServerPort;         /* The UDP port at their end            */
31
static int      TftpOurPort;            /* The UDP port at our end              */
32
static int      TftpTimeoutCount;
33
static unsigned TftpBlock;
34
static unsigned TftpLastBlock;
35
static int      TftpState;
36
#define STATE_RRQ       1
37
#define STATE_DATA      2
38
#define STATE_TOO_LARGE 3
39
#define STATE_BAD_MAGIC 4
40
 
41
char *tftp_filename;
42
 
43 140 julius
 
44
// running TFTP CRC value
45
unsigned long TFTP_CHKSUM;
46
 
47 2 marcus.erl
#ifdef CFG_DIRECT_FLASH_TFTP
48
extern flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
49
#endif
50
 
51
static __inline__ void
52
store_block (unsigned block, unsigned char * src, unsigned len)
53
{
54
        unsigned long offset = block * 512, newsize = offset + len;
55
#ifdef CFG_DIRECT_FLASH_TFTP
56
        int i, rc = 0;
57
 
58
        for (i=0; i<CFG_MAX_FLASH_BANKS; i++) {
59
                /* start address in flash? */
60
                if (global.src_addr + offset >= flash_info[i].start[0]) {
61
                        rc = 1;
62
                        break;
63
                }
64
        }
65
 
66
        if (rc) { /* Flash is destination for this packet */
67
                rc = flash_write ((unsigned char *)src, (unsigned long)(global.src_addr+offset), len);
68
                switch (rc) {
69
                case 0:  /* OK */
70
                        break;
71
                case 1: printf ("Timeout writing to Flash\n");
72
                        break;
73
                case 2: printf ("Flash not Erased\n");
74
                        break;
75
                case 4: printf ("Can't write to protected Flash sectors\n");
76
                        break;
77
                case 8: printf ("Outside available Flash\n");
78
                        break;
79
                case 16:printf ("Size must be aligned (multiple of 8?)\n");
80
                        break;
81
                default:
82
                        printf ("%s[%d] FIXME: rc=%d\n",__FILE__,__LINE__,rc);
83
                        break;
84
                }
85
                if (rc) {
86
                        NetState = NETLOOP_FAIL;
87
                        return;
88
                }
89
        }
90
        else
91
#endif /* CFG_DIRECT_FLASH_TFTP */
92 140 julius
 
93
//#define QUICK_ETHPACKET_COPY    
94
#ifdef QUICK_ETHPACKET_COPY
95
          {
96
            unsigned char * dst = (unsigned char*)(global.src_addr + offset);
97
            //printf("quick ethpacket copy: src: 0x%x dst: 0x%x, len: %d\n",(unsigned long)src, (unsigned long)dst, len);
98
            // First, align the destination address so we can copy words
99
            // If either src or dst are not word aligned, then we will never
100
            // be able to do word copies
101
            while((len) && ((((unsigned long)dst) & 0x3) || (((unsigned long)src) & 0x3)))
102
              {
103
                //              printf("bc: src: 0x%x dst: 0x%x, len: %d\n",(unsigned long)src, (unsigned long)dst, len);
104
                dst[0] = src[0];
105
                len--;
106
                dst++;
107
                src++;
108
 
109
              }
110
            unsigned long *wdst, *wsrc;
111
            wdst = (unsigned long*) dst;
112
            wsrc = (unsigned long*) src;
113
            while(len >= 4)
114
              {
115
                //printf("wc: src: 0x%x dst: 0x%x, len: %d\n",(unsigned long)src, (unsigned long)dst, len);
116
                wdst[0] = wsrc[0];
117
                wdst++; wsrc++;
118
                len -= 4;
119
                dst+=4;
120
                src+=4;
121
 
122
              }
123
            while (len)
124
              {
125
                //printf("cu: src: 0x%x dst: 0x%x, len: %d\n",(unsigned long)src, (unsigned long)dst, len);
126
                dst[0] = src[0];
127
                len--;
128
                dst++;
129
                src++;
130
              }
131
          }
132
#else
133
 
134
#ifdef TFTP_CALC_CRC
135
        // Call special memcpy that calculates CRC for us:
136
        TFTP_CHKSUM += memcpy_crc((void *)(global.src_addr + offset), src, len);
137
#else
138
        // Standard memcpy:
139 2 marcus.erl
        (void)memcpy((void *)(global.src_addr + offset), src, len);
140 140 julius
#endif
141
 
142 2 marcus.erl
 
143 140 julius
#endif    
144
 
145 2 marcus.erl
        if (NetBootFileXferSize < newsize)
146
                NetBootFileXferSize = newsize;
147
}
148
 
149
static void TftpSend (void);
150
static void TftpTimeout (void);
151
 
152
/**********************************************************************/
153
 
154
static void
155
TftpSend (void)
156
{
157
        volatile unsigned char *        pkt;
158
        volatile unsigned char *        xp;
159
        int                     len = 0;
160
 
161 140 julius
#ifdef ET_DEBUG
162 246 julius
        printf("TftpSend: %d\n", TftpState);
163 140 julius
#endif
164
 
165
 
166 2 marcus.erl
        /*
167
         *      We will always be sending some sort of packet, so
168
         *      cobble together the packet headers now.
169
         */
170
        pkt = NetTxPacket + ETHER_HDR_SIZE + IP_HDR_SIZE;
171
 
172
        switch (TftpState) {
173
 
174
        case STATE_RRQ:
175
                xp = pkt;
176 140 julius
                (*((unsigned short *)pkt)) = SWAP16c(TFTP_RRQ);
177
                pkt += sizeof(short);
178 2 marcus.erl
                strcpy ((char *)pkt, tftp_filename);
179
                pkt += strlen(tftp_filename) + 1;
180
                strcpy ((char *)pkt, "octet");
181
                pkt += 5 /*strlen("octet")*/ + 1;
182
                len = pkt - xp;
183 140 julius
 
184 2 marcus.erl
                break;
185
 
186
        case STATE_DATA:
187
                xp = pkt;
188 140 julius
                *((unsigned short *)pkt) = SWAP16c(TFTP_ACK);
189
                pkt += sizeof(short);
190
                *((unsigned short *)pkt) = SWAP16(TftpBlock);
191
                pkt += sizeof(short);
192 2 marcus.erl
                len = pkt - xp;
193
                break;
194
 
195
        case STATE_TOO_LARGE:
196
                xp = pkt;
197 140 julius
                *((unsigned short *)pkt) = SWAP16c(TFTP_ERROR);
198
                pkt += sizeof(short);
199
                *((unsigned short *)pkt) = SWAP16(3);
200
                pkt += sizeof(short);
201 2 marcus.erl
                strcpy ((char *)pkt, "File too large");
202
                pkt += 14 /*strlen("File too large")*/ + 1;
203
                len = pkt - xp;
204
                break;
205
 
206
        case STATE_BAD_MAGIC:
207
                xp = pkt;
208 140 julius
                *((unsigned short *)pkt) = SWAP16c(TFTP_ERROR);
209
                pkt += sizeof(short);
210
                *((unsigned short *)pkt) = SWAP16(2);
211
                pkt += sizeof(short);
212 2 marcus.erl
                strcpy ((char *)pkt, "File has bad magic");
213
                pkt += 18 /*strlen("File has bad magic")*/ + 1;
214
                len = pkt - xp;
215
                break;
216
        }
217
 
218
        NetSetEther (NetTxPacket, NetServerEther, PROT_IP);
219
        NetSetIP (NetTxPacket + ETHER_HDR_SIZE, NetServerIP,
220
                                        TftpServerPort, TftpOurPort, len);
221
        NetSendPacket (NetTxPacket, ETHER_HDR_SIZE + IP_HDR_SIZE + len);
222 140 julius
 
223 2 marcus.erl
}
224
 
225
 
226
static void
227
TftpHandler (unsigned char * pkt, unsigned dest, unsigned src, unsigned len)
228
{
229 140 julius
#ifdef ET_DEBUG
230
  //  printf("TftpHandler\n");
231
#endif
232 2 marcus.erl
        if (dest != TftpOurPort) {
233
                return;
234
        }
235
        if (TftpState != STATE_RRQ && src != TftpServerPort) {
236
                return;
237
        }
238
 
239
        if (len < 2) {
240
                return;
241
        }
242
        len -= 2;
243 140 julius
        switch (SWAP16(*((unsigned short *)pkt))) {
244 2 marcus.erl
 
245
        case TFTP_RRQ:
246
        case TFTP_WRQ:
247
        case TFTP_ACK:
248 140 julius
             pkt += sizeof(short);
249 2 marcus.erl
                break;
250
        default:
251
                break;
252
 
253
        case TFTP_DATA:
254 140 julius
                pkt += sizeof(short);
255 2 marcus.erl
                if (len < 2)
256
                        return;
257
                len -= 2;
258
                TftpBlock = SWAP16(*(unsigned short *)pkt);
259
                if (((TftpBlock - 1) % 10) == 0) {
260
                        putc ('#');
261
                        TftpTimeoutCount = 0;
262
                } else if ((TftpBlock % (10 * HASHES_PER_LINE)) == 0) {
263
                        printf ("\n\t ");
264
                }
265
 
266
                if (TftpState == STATE_RRQ) {
267
                        TftpState = STATE_DATA;
268
                        TftpServerPort = src;
269
                        TftpLastBlock = 0;
270
 
271
                        if (TftpBlock != 1) {   /* Assertion */
272
                                printf ("\nTFTP error: "
273
                                        "First block is not block 1 (%d)\n"
274
                                        "Starting again\n\n",
275
                                        TftpBlock);
276
                                NetStartAgain ();
277
                                break;
278
                        }
279
                }
280 246 julius
 
281 2 marcus.erl
                if (TftpBlock == TftpLastBlock) {
282 246 julius
                  /*
283
                   *    Same block again; resend ack (maybe got lost last time)
284
                   */
285
                  TftpSend ();
286
                  break;
287 2 marcus.erl
                }
288 246 julius
                else
289
                  {
290
                    TftpLastBlock = TftpBlock;
291
                    NetSetTimeout (TIMEOUT * TICKS_PER_SEC, TftpTimeout);
292
 
293
                    store_block (TftpBlock - 1, pkt + 2, len);
294
                  }
295
 
296 2 marcus.erl
                /*
297
                 *      Acknoledge the block just received, which will prompt
298
                 *      the server for the next one.
299
                 */
300
                TftpSend ();
301 246 julius
 
302 2 marcus.erl
                if (len < 512) {
303
                        /*
304
                         *      We received the whole thing.  Try to
305
                         *      run it.
306
                         */
307
                        printf ("\ndone\n");
308
                        NetState = NETLOOP_SUCCESS;
309
                }
310
                break;
311
 
312
        case TFTP_ERROR:
313 140 julius
                pkt += sizeof(short);
314 2 marcus.erl
                printf ("\nTFTP error: '%s' (%d)\n",
315 140 julius
                        pkt + 2, SWAP16(*(unsigned short *)pkt));
316 2 marcus.erl
                printf ("Starting again\n\n");
317
                NetStartAgain ();
318
                break;
319
        }
320 140 julius
 
321 2 marcus.erl
}
322
 
323
 
324
static void
325
TftpTimeout (void)
326
{
327
        if (++TftpTimeoutCount >= TIMEOUT_COUNT) {
328
                printf ("\nRetry count exceeded; starting again\n");
329
                NetStartAgain ();
330
        } else {
331
                printf ("T ");
332
                NetSetTimeout (TIMEOUT * TICKS_PER_SEC, TftpTimeout);
333
                TftpSend ();
334
        }
335
}
336
 
337
 
338
void
339
TftpStart (void)
340
{
341
#ifdef ET_DEBUG
342
        printf ("\nServer ethernet address %02x:%02x:%02x:%02x:%02x:%02x\n",
343
                NetServerEther[0],
344
                NetServerEther[1],
345
                NetServerEther[2],
346
                NetServerEther[3],
347
                NetServerEther[4],
348
                NetServerEther[5]
349
        );
350
#endif /* DEBUG */
351
 
352 140 julius
        TFTP_CHKSUM = 0; // Reset checksum
353
 
354 2 marcus.erl
        printf ("TFTP from server ");   print_IPaddr (NetServerIP);
355
        printf ("; our IP address is ");        print_IPaddr (NetOurIP);
356
 
357
        // Check if we need to send across this subnet
358
        if (NetOurGatewayIP && NetOurSubnetMask) {
359
            IPaddr_t OurNet     = NetOurIP    & NetOurSubnetMask;
360
            IPaddr_t ServerNet  = NetServerIP & NetOurSubnetMask;
361
 
362
            if (OurNet != ServerNet) {
363
                printf ("; sending through gateway ");
364
                print_IPaddr (NetOurGatewayIP) ;
365
            }
366
        }
367
        putc ('\n');
368
 
369
        printf ("Filename '%s'.", tftp_filename);
370
 
371
        if (NetBootFileSize) {
372
            printf (" Size is %d%s kB => %x Bytes",
373
                NetBootFileSize/2,
374
                (NetBootFileSize%2) ? ".5" : "",
375
                NetBootFileSize<<9);
376
        }
377
 
378
        putc ('\n');
379
 
380
        printf ("Load address: 0x%lx\n", global.src_addr);
381
 
382
        printf ("Loading: *\b");
383
 
384
        NetSetTimeout (TIMEOUT * TICKS_PER_SEC, TftpTimeout);
385
        NetSetHandler (TftpHandler);
386
 
387
        TftpServerPort = WELL_KNOWN_PORT;
388
        TftpTimeoutCount = 0;
389
        TftpState = STATE_RRQ;
390
        TftpOurPort = 1024 + (get_timer(0) % 3072);
391
 
392
        TftpSend ();
393
}
394
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.