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

Subversion Repositories amber

[/] [amber/] [trunk/] [sw/] [boot-loader-ethmac/] [telnet.c] - Blame information for rev 82

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 61 csantifort
/*----------------------------------------------------------------
2
//                                                              //
3
//  boot-loader-ethmac.c                                        //
4
//                                                              //
5
//  This file is part of the Amber project                      //
6
//  http://www.opencores.org/project,amber                      //
7
//                                                              //
8
//  Description                                                 //
9
//  The main functions for the boot loader application. This    //
10 78 csantifort
//  application is embedded in the FPGA's SRAM and is used      //
11 61 csantifort
//  to load larger applications into the DDR3 memory on         //
12
//  the development board.                                      //
13
//                                                              //
14
//  Author(s):                                                  //
15
//      - Conor Santifort, csantifort.amber@gmail.com           //
16
//                                                              //
17
//////////////////////////////////////////////////////////////////
18
//                                                              //
19
// Copyright (C) 2011 Authors and OPENCORES.ORG                 //
20
//                                                              //
21
// This source file may be used and distributed without         //
22
// restriction provided that this copyright statement is not    //
23
// removed from the file and that any derivative work contains  //
24
// the original copyright notice and the associated disclaimer. //
25
//                                                              //
26
// This source file is free software; you can redistribute it   //
27
// and/or modify it under the terms of the GNU Lesser General   //
28
// Public License as published by the Free Software Foundation; //
29
// either version 2.1 of the License, or (at your option) any   //
30
// later version.                                               //
31
//                                                              //
32
// This source is distributed in the hope that it will be       //
33
// useful, but WITHOUT ANY WARRANTY; without even the implied   //
34
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
35
// PURPOSE.  See the GNU Lesser General Public License for more //
36
// details.                                                     //
37
//                                                              //
38
// You should have received a copy of the GNU Lesser General    //
39
// Public License along with this source; if not, download it   //
40
// from http://www.opencores.org/lgpl.shtml                     //
41
//                                                              //
42
----------------------------------------------------------------*/
43
 
44 80 csantifort
#include "address_map.h"
45 61 csantifort
#include "timer.h"
46
#include "line-buffer.h"
47
#include "packet.h"
48 81 csantifort
#include "serial.h"
49 61 csantifort
#include "tcp.h"
50
#include "telnet.h"
51 81 csantifort
#include "utilities.h"
52 61 csantifort
 
53 81 csantifort
/* Global variables */
54
telnet_t*   first_telnet_g = NULL;
55
 
56
 
57
/* input argument is a pointer to the previous socket,
58
   if this is the first socket object, then it is NULL */
59
telnet_t* new_telnet(telnet_t* prev)
60
{
61
    telnet_t* telnet;
62
    app_t* app;
63
 
64
    telnet = (telnet_t*) malloc(sizeof(telnet_t));
65
    app = (app_t*) malloc(sizeof(app_t));
66
 
67
    /* cross reference between the two objects */
68
    app->telnet = telnet;
69
    app->type   = APP_TELNET;
70
    telnet->app = app;
71
 
72
    telnet->txbuf = init_line_buffer(0x80000);
73
    telnet->rxbuf = init_line_buffer(0x1000);
74
 
75
    telnet->sent_opening_message = 0;
76
    telnet->echo_mode = 0;
77
    telnet->connection_state = TELNET_CLOSED;
78
    telnet->options_sent = 0;
79
 
80
    /* Chain the socket objects together */
81
    if (prev == NULL){
82
        telnet->first = telnet;
83
        telnet->id = 0;
84
        }
85
    else {
86
        telnet->first = prev->first;
87
        telnet->id = prev->id + 1;
88
        prev->next = telnet;
89
        }
90
    telnet->next  = NULL;
91
 
92
    return telnet;
93
}
94
 
95
 
96
 
97
void listen_telnet ()
98
{
99
    telnet_t* telnet;
100
    int telnet_socket;
101
 
102
    /* Add a new socket to the end of the list */
103
    if (first_telnet_g == NULL) {
104
        trace("first_telnet_g == NULL");
105
        first_telnet_g = new_telnet(NULL);
106
        telnet = first_telnet_g;
107
    }
108
    else {
109
        telnet = first_telnet_g;
110
        for(;;){
111
            if (telnet->next!=NULL)
112
                telnet=telnet->next;
113
            else
114
                break;
115
            }
116
        telnet = new_telnet(telnet);
117
    }
118
 
119
    /* Create a new socket and listen on it at port 23 */
120
    telnet_socket = listen_socket(23, telnet->app);
121
    trace("telnet_socket = %d", telnet_socket);
122
}
123
 
124
 
125
 
126
void telnet_disconnect(app_t * app)
127
{
128
    telnet_t* telnet;
129
    trace("disconnect!");
130
    telnet = (telnet_t*)(app->telnet);
131
    telnet->connection_state = TELNET_CLOSED;
132
    telnet->options_sent = 0;
133
    telnet->sent_opening_message = 0;
134
    telnet->echo_mode = 0;  // reset this setting
135
}
136
 
137
 
138
 
139 61 csantifort
void parse_telnet_options(char* buf, socket_t* socket)
140
{
141
    int     i;
142
    int     stage = 0;
143
    char    stage1;
144 81 csantifort
    telnet_t* telnet = (telnet_t*) socket->app->telnet;
145 78 csantifort
 
146 61 csantifort
    for (i=0;i<socket->rx_packet->tcp_payload_len;i++) {
147 78 csantifort
 
148 61 csantifort
        if (stage == 0) {
149
            switch (buf[i]) {
150
                case 241: stage = 0; break;  // NOP
151 78 csantifort
                case 255: stage = 1;
152 81 csantifort
                                 if (telnet->connection_state == TELNET_CLOSED) {
153
                                     telnet->connection_state = TELNET_OPEN;
154 61 csantifort
                                    }
155
                         break;  // IAC
156 78 csantifort
 
157
                default:  if (buf[i] < 128)
158 61 csantifort
                    goto telnet_payload;
159
            }
160 78 csantifort
 
161 61 csantifort
        } else if (stage == 1) {
162
            stage1 = buf[i];
163
            switch (buf[i]) {
164
                case 241        : stage = 0; break;  // NOP
165
                case 250        : stage = 2; break;  // SB
166
                case TELNET_WILL: stage = 2; break;  // 0xfb WILL
167
                case TELNET_WONT: stage = 2; break;  // 0xfc WONT
168
                case TELNET_DO  : stage = 2; break;  // 0xfd DO
169
                case TELNET_DONT: stage = 2; break;  // 0xfe DONT
170
                default         : stage = 2; break;
171
            }
172 78 csantifort
 
173 61 csantifort
        } else {  // stage = 2
174 78 csantifort
            stage = 0;
175 61 csantifort
            switch (buf[i]) {
176
                case 1:   // echo
177
                    /* Client request that server echos stuff back to client */
178
                    if (stage1 == TELNET_DO)
179 81 csantifort
                        telnet->echo_mode = 1;
180 61 csantifort
                    /* Client request that server does not echo stuff back to client */
181
                    else if (stage1 == TELNET_DONT)
182 81 csantifort
                        telnet->echo_mode = 0;
183 61 csantifort
                    break;
184 78 csantifort
 
185 61 csantifort
                case 3:   break;  // suppress go ahead
186
                case 5:   break;  // status
187
                case 6:   break;  // time mark
188
                case 24:  break;  // terminal type
189
                case 31:  break;  // window size
190
                case 32:  break;  // terminal speed
191
                case 33:  break;  // remote flow control
192
                case 34:  break;  // linemode
193
                case 35:  break;  // X display location
194
                case 39:  break;  // New environmental variable option
195
                default:  break;
196
                }
197
            }
198
        }
199
 
200 78 csantifort
    return;
201
 
202 61 csantifort
    telnet_payload:
203
        socket->rx_packet->telnet_payload_len = socket->rx_packet->tcp_payload_len - i;
204
        parse_telnet_payload(&buf[i], socket);
205
}
206
 
207
 
208
void parse_telnet_payload(char * buf, socket_t* socket)
209
{
210
    int i;
211
    int cr = 0;
212
    int windows = 0;
213 81 csantifort
    telnet_t* telnet = (telnet_t*) socket->app->telnet;
214
 
215 61 csantifort
    for (i=0;i<socket->rx_packet->telnet_payload_len;i++) {
216 78 csantifort
        if (buf[i] == '\n')
217 61 csantifort
            windows = 1;
218
        else if (buf[i] < 128 && buf[i] != 0) {
219
            /* end of a line */
220
            /* receive \r\n from Windows, \r from Linux */
221
            if (buf[i] == '\r') {
222
                cr=1;
223 81 csantifort
                put_byte(telnet->rxbuf, buf[i], 1); /* last byte of line */
224 78 csantifort
                }
225 61 csantifort
            else {
226 81 csantifort
                put_byte(telnet->rxbuf, buf[i], 0); /* not last byte of line */
227 78 csantifort
                }
228 61 csantifort
            }
229
        }
230 78 csantifort
 
231 81 csantifort
    if (telnet->echo_mode) {
232 61 csantifort
        if (cr && !windows) {
233
            buf[socket->rx_packet->telnet_payload_len] = '\n';
234
            socket->rx_packet->telnet_payload_len++;
235
            }
236
        tcp_reply(socket, buf, socket->rx_packet->telnet_payload_len);
237
        }
238
}
239
 
240
 
241
void telnet_options(socket_t* socket)
242
{
243
    char buf[3];
244
 
245
    // telnet options
246
    // Will echo - advertise that I have the ability to echo back commands to the client
247 78 csantifort
    buf[0] = 0xff; buf[1] = TELNET_WILL; buf[2] = 0x01;
248 61 csantifort
    tcp_reply(socket, buf, 3);
249
 
250
}
251
 
252
 
253
void telnet_tx(socket_t* socket, line_buf_t* txbuf)
254
{
255
    int line_len;
256
    int total_line_len;
257
    char* line;
258
    char* first_line;
259
 
260 78 csantifort
    /* Parse telnet tx buffer
261
       Grab as many lines as possible to stuff into a packet to transmit */
262
    line_len = get_line(txbuf, &first_line);
263
    if (line_len) {
264
        total_line_len = line_len;
265
        while (total_line_len < MAX_TELNET_TX && line_len) {
266
            line_len = get_line(txbuf, &line);
267
            total_line_len += line_len;
268
            }
269
        tcp_tx(socket, first_line, total_line_len);
270
        }
271 61 csantifort
}
272 78 csantifort
 
273 80 csantifort
 
274 81 csantifort
/* Create a new telnet option, and a new socket to listen on */
275 80 csantifort
void process_telnet(socket_t* socket)
276
{
277
    char* line;
278 81 csantifort
    telnet_t* telnet = (telnet_t*) socket->app->telnet;
279 80 csantifort
 
280 81 csantifort
    if (!telnet->options_sent){
281 80 csantifort
        telnet_options(socket);
282 81 csantifort
        telnet->options_sent = 1;
283 80 csantifort
        }
284
 
285
    else {
286
        /* Send telnet greeting */
287 81 csantifort
        if (!telnet->sent_opening_message){
288
            put_line (telnet->txbuf, "Amber Processor Boot Loader\r\n> ");
289
            telnet->sent_opening_message = 1;
290 82 csantifort
 
291
            /* connecting on this socket, so create a new socket to listen
292
               for any other connect requests from telnet clients */
293 81 csantifort
            trace("telnet listen on new socket");
294
            listen_telnet();
295 80 csantifort
            }
296
 
297
        /* Parse telnet rx buffer */
298 81 csantifort
        if (get_line(telnet->rxbuf, &line))
299
            parse_command (telnet, line);
300 80 csantifort
 
301
        /* Transmit text from telnet tx buffer */
302 81 csantifort
        telnet_tx(socket, telnet->txbuf);
303 80 csantifort
        }
304
}
305
 
306
 
307
 
308
/* Parse a command line passed from main and execute the command */
309
/* returns the length of the reply string */
310 81 csantifort
int parse_command (telnet_t* telnet, char* line)
311 80 csantifort
{
312
    unsigned int start_addr;
313
    unsigned int address;
314
    unsigned int range;
315
    int len, error = 0;
316
 
317 81 csantifort
    socket_t* socket = (socket_t*) telnet->app->socket;
318
 
319 80 csantifort
    /* All commands are just a single character.
320
       Just ignore anything else  */
321
    switch (line[0]) {
322
        /* Disconnect */
323
        case 'e':
324
        case 'x':
325
        case 'q':
326 81 csantifort
            trace("set disconnect flag on socket");
327 80 csantifort
            socket->tcp_disconnect = 1;
328
            return 0;
329
 
330
        case 'r': /* Read mem */
331
            {
332
            if (len = get_hex (&line[2], &start_addr)) {
333
                if (len = get_hex (&line[3+len], &range)) {
334
                    for (address=start_addr; address<start_addr+range; address+=4) {
335 81 csantifort
                        put_line (telnet->txbuf, "0x%08x 0x%08x\r\n",
336 80 csantifort
                                    address, *(unsigned int *)address);
337
                        }
338
                    }
339
                else {
340 81 csantifort
                    put_line (telnet->txbuf, "0x%08x 0x%08x\r\n",
341 80 csantifort
                                    start_addr, *(unsigned int *)start_addr);
342
                    }
343
                }
344
            else
345
                error=1;
346
            break;
347
            }
348
 
349
 
350
        case 'h': {/* Help */
351 81 csantifort
            put_line (telnet->txbuf, "You need help alright\r\n");
352 80 csantifort
            break;
353
            }
354
 
355
 
356
        case 's': {/* Status */
357 81 csantifort
            put_line (telnet->txbuf, "Socket ID           %d\r\n", socket->id);
358
            put_line (telnet->txbuf, "Packets received    %d\r\n", socket->packets_received);
359
            put_line (telnet->txbuf, "Packets transmitted %d\r\n", socket->packets_sent);
360
            put_line (telnet->txbuf, "Packets resent      %d\r\n", socket->packets_resent);
361
            put_line (telnet->txbuf, "TCP checksum errors %d\r\n", tcp_checksum_errors_g);
362 80 csantifort
 
363 81 csantifort
            put_line (telnet->txbuf, "Counterparty IP %d.%d.%d.%d\r\n",
364 80 csantifort
                socket->rx_packet->src_ip[0],
365
                socket->rx_packet->src_ip[1],
366
                socket->rx_packet->src_ip[2],
367
                socket->rx_packet->src_ip[3]);
368
 
369 81 csantifort
            put_line (telnet->txbuf, "Counterparty Port %d\r\n",
370 80 csantifort
                socket->rx_packet->tcp_src_port);
371
 
372 81 csantifort
            put_line (telnet->txbuf, "Malloc pointer 0x%08x\r\n",
373 80 csantifort
                *(unsigned int *)(ADR_MALLOC_POINTER));
374 81 csantifort
            put_line (telnet->txbuf, "Malloc count %d\r\n",
375 80 csantifort
                *(unsigned int *)(ADR_MALLOC_COUNT));
376 81 csantifort
            put_line (telnet->txbuf, "Uptime %d seconds\r\n",
377
                current_time_g->seconds);
378 80 csantifort
            break;
379
            }
380
 
381
 
382
        default: {
383
            error=1; break;
384
            }
385
        }
386
 
387
 
388
    if (error)
389 81 csantifort
            put_line (telnet->txbuf, "You're not making any sense\r\n",
390 80 csantifort
                        line[0], line[1], line[2]);
391
 
392 81 csantifort
    put_line (telnet->txbuf, "> ");
393 80 csantifort
    return 0;
394
}
395 81 csantifort
 

powered by: WebSVN 2.1.0

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