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

Subversion Repositories openrisc

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

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 405 julius
 
272 2 marcus.erl
                        if (TftpBlock != 1) {   /* Assertion */
273
                                printf ("\nTFTP error: "
274
                                        "First block is not block 1 (%d)\n"
275
                                        "Starting again\n\n",
276
                                        TftpBlock);
277
                                NetStartAgain ();
278
                                break;
279
                        }
280
                }
281 405 julius
 
282 2 marcus.erl
                if (TftpBlock == TftpLastBlock) {
283 405 julius
#ifdef ET_DEBUG
284
                  printf("block %d - repeated\n",TftpLastBlock);
285
#endif
286 246 julius
                  /*
287
                   *    Same block again; resend ack (maybe got lost last time)
288
                   */
289
                  TftpSend ();
290
                  break;
291 2 marcus.erl
                }
292 246 julius
                else
293
                  {
294 405 julius
#ifdef ET_DEBUG
295
                    printf("block %d - OK\n",TftpLastBlock);
296
#endif
297 246 julius
                    TftpLastBlock = TftpBlock;
298
                    NetSetTimeout (TIMEOUT * TICKS_PER_SEC, TftpTimeout);
299
 
300
                    store_block (TftpBlock - 1, pkt + 2, len);
301
                  }
302
 
303 2 marcus.erl
                /*
304
                 *      Acknoledge the block just received, which will prompt
305
                 *      the server for the next one.
306
                 */
307
                TftpSend ();
308 246 julius
 
309 2 marcus.erl
                if (len < 512) {
310
                        /*
311
                         *      We received the whole thing.  Try to
312
                         *      run it.
313
                         */
314
                        printf ("\ndone\n");
315
                        NetState = NETLOOP_SUCCESS;
316
                }
317
                break;
318
 
319
        case TFTP_ERROR:
320 140 julius
                pkt += sizeof(short);
321 2 marcus.erl
                printf ("\nTFTP error: '%s' (%d)\n",
322 140 julius
                        pkt + 2, SWAP16(*(unsigned short *)pkt));
323 2 marcus.erl
                printf ("Starting again\n\n");
324
                NetStartAgain ();
325
                break;
326
        }
327 140 julius
 
328 2 marcus.erl
}
329
 
330
 
331
static void
332
TftpTimeout (void)
333
{
334
        if (++TftpTimeoutCount >= TIMEOUT_COUNT) {
335
                printf ("\nRetry count exceeded; starting again\n");
336
                NetStartAgain ();
337
        } else {
338
                printf ("T ");
339
                NetSetTimeout (TIMEOUT * TICKS_PER_SEC, TftpTimeout);
340
                TftpSend ();
341
        }
342
}
343
 
344
 
345
void
346
TftpStart (void)
347
{
348
#ifdef ET_DEBUG
349
        printf ("\nServer ethernet address %02x:%02x:%02x:%02x:%02x:%02x\n",
350
                NetServerEther[0],
351
                NetServerEther[1],
352
                NetServerEther[2],
353
                NetServerEther[3],
354
                NetServerEther[4],
355
                NetServerEther[5]
356
        );
357
#endif /* DEBUG */
358
 
359 140 julius
        TFTP_CHKSUM = 0; // Reset checksum
360
 
361 2 marcus.erl
        printf ("TFTP from server ");   print_IPaddr (NetServerIP);
362
        printf ("; our IP address is ");        print_IPaddr (NetOurIP);
363
 
364
        // Check if we need to send across this subnet
365
        if (NetOurGatewayIP && NetOurSubnetMask) {
366
            IPaddr_t OurNet     = NetOurIP    & NetOurSubnetMask;
367
            IPaddr_t ServerNet  = NetServerIP & NetOurSubnetMask;
368
 
369
            if (OurNet != ServerNet) {
370
                printf ("; sending through gateway ");
371
                print_IPaddr (NetOurGatewayIP) ;
372
            }
373
        }
374
        putc ('\n');
375
 
376
        printf ("Filename '%s'.", tftp_filename);
377
 
378
        if (NetBootFileSize) {
379
            printf (" Size is %d%s kB => %x Bytes",
380
                NetBootFileSize/2,
381
                (NetBootFileSize%2) ? ".5" : "",
382
                NetBootFileSize<<9);
383
        }
384
 
385
        putc ('\n');
386
 
387
        printf ("Load address: 0x%lx\n", global.src_addr);
388
 
389
        printf ("Loading: *\b");
390
 
391
        NetSetTimeout (TIMEOUT * TICKS_PER_SEC, TftpTimeout);
392
        NetSetHandler (TftpHandler);
393
 
394
        TftpServerPort = WELL_KNOWN_PORT;
395
        TftpTimeoutCount = 0;
396
        TftpState = STATE_RRQ;
397
        TftpOurPort = 1024 + (get_timer(0) % 3072);
398
 
399
        TftpSend ();
400
}
401
 

powered by: WebSVN 2.1.0

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