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 179

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

powered by: WebSVN 2.1.0

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