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

Subversion Repositories openrisc

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

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

powered by: WebSVN 2.1.0

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