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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [orpmon/] [services/] [tftp.c] - Blame information for rev 833

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

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

powered by: WebSVN 2.1.0

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