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

Subversion Repositories amber

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

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

Line No. Rev Author Line
1 80 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
//  application is embedded in the FPGA's SRAM and is used      //
11
//  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
#include "amber_registers.h"
45
#include "address_map.h"
46
#include "line-buffer.h"
47
#include "timer.h"
48
#include "utilities.h"
49
#include "packet.h"
50
#include "udp.h"
51
#include "tcp.h"
52
#include "tftp.h"
53
#include "elfsplitter.h"
54
 
55
 
56
block_t*    udp_file_g = NULL;
57
block_t*    udp_current_block_g = NULL;
58
time_t*     reboot_timer_g;
59
int         reboot_stage_g;
60
 
61
 
62
block_t* init_buffer_512()
63
{
64
    block_t* block = malloc(sizeof(block_t));
65
    block->buf512 = malloc(512);
66
    block->next   = NULL;
67
    block->bytes  = 0;
68
    block->last_block  = 0;
69
    block->total_bytes  = 0;
70
    block->total_blocks  = 0;
71
    block->ready  = 0;
72
    block->filename  = NULL;
73
    block->linux_boot = 0;
74
    return block;
75
}
76
 
77
 
78
void parse_tftp_packet(char * buf, packet_t* rx_packet, int tftp_len, unsigned int udp_src_port, unsigned int udp_dst_port)
79
{
80
    int mode_offset;
81
    int binary_mode;
82
 
83
    unsigned int opcode = buf[8]<<8|buf[9];
84
    unsigned int block  = buf[10]<<8|buf[11];
85
 
86
    mode_offset = next_string(&buf[10]);
87
    binary_mode = strcmp("octet", &buf[10+mode_offset]);
88
 
89
    switch (opcode) {
90
 
91
        case  UDP_READ:
92
            udp_reply(rx_packet, udp_dst_port, udp_src_port, 0, UDP_ERROR);
93
            break;
94
 
95
        case  UDP_WRITE:
96
            udp_file_g = init_buffer_512();
97
            udp_file_g->filename = malloc(256);
98
            strcpy(udp_file_g->filename, &buf[10]);
99
 
100
            if (strncmp(&buf[10], "vmlinux", 7) == 0)
101
                udp_file_g->linux_boot = 1;
102
 
103
            udp_current_block_g = udp_file_g;
104
 
105
            if (binary_mode)
106
                udp_reply(rx_packet, udp_dst_port, udp_src_port, 0, UDP_ACK);
107
            else
108
                udp_reply(rx_packet, udp_dst_port, udp_src_port, 0, UDP_ERROR);
109
            break;
110
 
111
 
112
        case  UDP_DATA:
113
            udp_reply(rx_packet, udp_dst_port, udp_src_port, block, UDP_ACK);
114
 
115
            if (block > udp_file_g->last_block) {
116
                // Have not already received this block
117
                udp_file_g->last_block = block;
118
 
119
                /* receive and save a block */
120
                udp_current_block_g->bytes = tftp_len;
121
                udp_file_g->total_bytes += tftp_len;
122
                udp_file_g->total_blocks++;
123
 
124
                memcpy(udp_current_block_g->buf512, &buf[12], tftp_len);
125
 
126
                /* Prepare the next block */
127
                if (tftp_len == 512) {
128
                    udp_current_block_g->next = init_buffer_512();
129
                    udp_current_block_g = udp_current_block_g->next;
130
                    }
131
                else { /* Last block */
132
                    udp_file_g->ready = 1;
133
                    }
134
                }
135
            break;
136
 
137
 
138
        default: break;
139
        }
140
}
141
 
142
 
143
 
144
void init_tftp()
145
{
146
    reboot_timer_g = new_timer();
147
    reboot_stage_g = 0;
148
}
149
 
150
 
151
void process_tftp ()
152
{
153
    socket_t* socket;
154
 
155
    /* Check for newly downloaded tftp file. Add to all tx buffers */
156
    /* Has a file been uploaded via tftp ? */
157
    if (udp_file_g != NULL) {
158
        /* Notify telnet clients that file has been received */
159
        if (udp_file_g->ready) {
160
            udp_file_g->ready = 0;
161
 
162
            print_serial("Received file %s, %d bytes",
163
                udp_file_g->filename, udp_file_g->total_bytes);
164
            if (udp_file_g->linux_boot)
165
                print_serial(", linux image detected\r\n");
166
            else
167
                print_serial("\r\n");
168
 
169
            if (process_file() == 0) {
170
                /* Disconnect in 1 second */
171
                set_timer(reboot_timer_g, 1000);
172
                }
173
            else
174
                print_serial("Not an elf file\r\n");
175
            }
176
        }
177
 
178
    /* reboot timer expired */
179
    if (timer_expired(reboot_timer_g)) {
180
        /* First stage of reboot sequence is to nicely disconnect */
181
        if (reboot_stage_g == 0) {
182
            set_timer(reboot_timer_g, 1000);
183
            reboot_stage_g = 1;
184
            socket = first_socket_g;
185
            for(;;){
186
                socket->tcp_disconnect = 1;
187
                if (socket->next!=NULL)
188
                    socket=socket->next;
189
                else
190
                    break;
191
                }
192
            }
193
        else {
194
        /* Second stage of reboot sequence is to turn off ethmac and then jump to restart vector */
195
            close_link();
196
            reboot();
197
            }
198
        }
199
}
200
 
201
 
202
 
203
/* copy tftp file into a single contiguous buffer so
204
   if can be processed by elf splitter */
205
int process_file()
206
{
207
    block_t* block;
208
    char*    buf512;
209
    char*    tftp_file;
210
    char*    line;
211
    int      line_len;
212
    int      ret;
213
 
214
    tftp_file = malloc(udp_file_g->total_bytes);
215
 
216
    block = udp_file_g;
217
    buf512= tftp_file;
218
 
219
    while (block->next) {
220
        memcpy(buf512, block->buf512, block->bytes);
221
        buf512=&buf512[512];
222
        block=block->next;
223
        }
224
    memcpy(buf512, block->buf512, block->bytes);
225
    buf512=&buf512[512];
226
 
227
    return elfsplitter(tftp_file);
228
}
229
 
230
 
231
/* Disable interrupts
232
   Load new values into the interrupt vector memory space
233
   Jump to address 0
234
*/
235
void reboot()
236
{
237
   int i;
238
 
239
   /* Disable all interrupts */
240
   /* Disable ethmac_int interrupt */
241
   /* Disable timer 0 interrupt in interrupt controller */
242
   *(unsigned int *) ( ADR_AMBER_IC_IRQ0_ENABLECLR ) = 0x120;
243
 
244
   for(i=0;i<MEM_BUF_ENTRIES;i++)
245
       if (elf_mem0_g->entry[i].valid)
246
           *(char *)(i) = elf_mem0_g->entry[i].data;
247
 
248
   if (udp_file_g->linux_boot) {
249
        print_serial("linux reboot\n\r");
250
        _jump_to_program(LINUX_JUMP_ADR);
251
        }
252
   else {
253
        print_serial("normal reboot\n\r");
254
        _restart();
255
        }
256
}

powered by: WebSVN 2.1.0

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