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

Subversion Repositories or1k

[/] [or1k/] [branches/] [oc/] [orpmon/] [services/] [tftp.c] - Blame information for rev 1771

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

powered by: WebSVN 2.1.0

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