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

Subversion Repositories or1k

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

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

powered by: WebSVN 2.1.0

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