1 /* *********************************************************************
2 * Broadcom Common Firmware Environment (CFE)
4 * HTTP Protocol File: net_http.c
6 * This file contains a very simple TCP and HTTP. The basic goals of this
7 * tcp are to be "good enough for firmware." We try to be
8 * correct in our protocol implementation, but not very fancy.
9 * In particular, we don't deal with out-of-order segments,
10 * we don't hesitate to copy data more then necessary, etc.
11 * We strive to implement important protocol features
12 * like slow start, nagle, etc., but even these things are
13 * subsetted and simplified as much as possible.
17 *********************************************************************
19 * Copyright 2000,2001,2002,2003
20 * Broadcom Corporation. All rights reserved.
22 * This software is furnished under license and may be used and
23 * copied only in accordance with the following terms and
24 * conditions. Subject to these conditions, you may download,
25 * copy, install, use, modify and distribute modified or unmodified
26 * copies of this software in source and/or binary form. No title
27 * or ownership is transferred hereby.
29 * 1) Any source code used, modified or distributed must reproduce
30 * and retain this copyright notice and list of conditions
31 * as they appear in the source file.
33 * 2) No right is granted to use any trade name, trademark, or
34 * logo of Broadcom Corporation. The "Broadcom Corporation"
35 * name may not be used to endorse or promote products derived
36 * from this software without the prior written permission of
37 * Broadcom Corporation.
39 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
40 * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
41 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
42 * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
43 * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
44 * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
45 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
46 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
47 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
48 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
49 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
50 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
51 * THE POSSIBILITY OF SUCH DAMAGE.
52 ********************************************************************* */
54 #include "lib_types.h"
55 #include "lib_string.h"
56 #include "lib_queue.h"
57 #include "lib_malloc.h"
58 #include "lib_printf.h"
59 #include "lib_scanf.h"
60 #include <bcmendian.h>
62 #include "net_ether.h"
65 #include "net_ip_internal.h"
68 #include "cfe_devfuncs.h"
69 #include "cfe_ioctl.h"
70 #include "cfe_timer.h"
71 #include "cfe_error.h"
73 #include "cfe_flashimage.h"
79 #define NULL (void *)0
82 /* The HTTP server states: */
83 #define HTTP_NOT_READY 0
89 #define HTTP_UPLOAD_BOOT 6
90 #define HTTP_UPLOAD_EXE 7
93 #define PRINT(x) printf("%s", x)
94 #define PRINTLN(x) printf("%s\n", x)
102 void *ti_ref
; /* ref data for IP layer */
103 ip_info_t
*ti_ipinfo
; /* IP layer handle */
105 uint32_t ti_iss
; /* initial sequence number */
109 #define UL_MULTIPART 1
113 unsigned char ul_state
;
114 struct http_info_s
*ti
;
128 static struct httpd_state httpd_state
;
134 #define ISO_slash 0x2f
138 #define ISO_space 0x20
143 #define ISO_hash 0x23
144 #define ISO_period 0x2e
146 /* Forward Declarations */
147 static int _tcphttp_rx_callback(void *ref
, ebuf_t
*buf
, uint8_t *destaddr
, uint8_t *srcaddr
);
148 static void _tcphttp_protosend(http_info_t
*ti
, tcb_t
*tcb
);
150 static int httpd_accept(struct httpd_state
*hs
, http_info_t
*ti
, tcb_t
*tcb
);
151 static int httpd_appcall(struct httpd_state
*hs
);
152 static void httpd_defercall(struct httpd_state
*hs
);
153 static void httpd_page_init(struct httpd_state
*hs
);
154 static void httpd_page_end(struct httpd_state
*hs
, int rc
, int f
);
155 static int httpd_do_cmd(struct httpd_state
*hs
);
156 static int httpd_load_program(struct httpd_state
*hs
);
157 static int httpd_do_ul(struct httpd_state
*hs
);
158 static void httpd_printf(struct httpd_state
*hs
, char *templat
, ...);
159 static int trx_validate(uint8_t *ptr
, int *insize
);
160 static int httpd_write_flash(char *flashdev
, uint8
*load_addr
, int len
);
162 extern int ui_docommands(char *buf
);
163 extern int flash_validate(uint8_t *ptr
, int bufsize
, int insize
, uint8_t **outptr
, int *outsize
);
164 extern void ui_get_flash_buf(uint8_t **bufptr
, int *bufsize
);
165 extern unsigned int flash_crc32(const unsigned char *databuf
, unsigned int datalen
);
168 int _tcp_dumpflags
= 1;
170 int _tcp_dumpflags
= 0;
171 #endif /* _TCP_DEBUG */
176 * Initialize the TCP module. We set up our data structures
177 * and register ourselves with the IP layer.
180 * ipi - IP information
181 * ref - will be passed back to IP as needed
184 * http_info_t structure, or NULL if problems
187 _tcphttp_init(ip_info_t
*ipi
, void *ref
)
189 extern int32_t _getticks(void); /* return value of CP0 COUNT */
190 http_info_t
*ti
= NULL
;
193 ti
= (http_info_t
*)KMALLOC(sizeof(http_info_t
), 0);
204 memset(tcb
, 0, sizeof(tcb_t
));
207 * Set up initial state.
209 _tcp_setstate(tcb
, TCPSTATE_CLOSED
);
212 * Set up the initial sequence number
214 ti
->ti_iss
= (uint32_t)_getticks();
217 * Register our protocol with IP
220 _ip_register(ipi
, IPPROTO_TCP
, _tcphttp_rx_callback
, ti
);
222 httpd_state
.state
= HTTP_NOGET
;
229 * De-initialize the TCP layer, unregistering from the IP layer.
232 * info - our http_info_t, from _tcp_init()
238 _tcphttp_uninit(http_info_t
*info
)
243 _ip_deregister(info
->ti_ipinfo
, IPPROTO_TCP
);
246 * Free up the info structure
251 memset(&httpd_state
, 0, sizeof(httpd_state
));
256 * _tcp_protosend(ti,tcb)
258 * Transmit "protocol messages" on the tcb. This is used for
259 * sending SYN, FIN, ACK, and other control packets.
262 * ti - tcp infomration
263 * tcb - tcb we're interested in
269 _tcphttp_protosend(http_info_t
*ti
, tcb_t
*tcb
)
277 uint8_t pseudoheader
[12];
281 * Allocate a buffer and remember the pointer to where
284 b
= _ip_alloc(ti
->ti_ipinfo
);
288 tcphdr
= ebuf_ptr(b
) + ebuf_length(b
);
291 * Build the TCP header
293 flags
= tcb
->tcb_txflags
| (TCPHDRFLG(TCP_HDR_LENGTH
));
294 hdrlen
= TCP_HDR_LENGTH
;
297 * Fill in the fields according to the RFC.
299 ebuf_append_u16_be(b
, tcb
->tcb_lclport
); /* Local and remote ports */
300 ebuf_append_u16_be(b
, tcb
->tcb_peerport
);
301 ebuf_append_u32_be(b
, tcb
->tcb_sendnext
); /* sequence and ack numbers */
302 ebuf_append_u32_be(b
, tcb
->tcb_rcvnext
);
303 ebuf_append_u16_be(b
, flags
); /* Flags */
304 ebuf_append_u16_be(b
, tcb
->tcb_sendwindow
); /* Window size */
305 cksumptr
= ebuf_ptr(b
) + ebuf_length(b
);
306 ebuf_append_u16_be(b
, 0); /* dummy checksum for calculation */
307 ebuf_append_u16_be(b
, 0); /* Urgent Pointer (not used) */
310 if (tcb
->txlen
> 0) {
311 memcpy(b
->eb_ptr
+ b
->eb_length
, tcb
->tcb_txbuf
, tcb
->txlen
);
312 b
->eb_length
+= tcb
->txlen
;
313 tcb
->tcb_txbuf
= NULL
;
318 * Build the pseudoheader, which is part of the checksum calculation
320 _ip_getaddr(ti
->ti_ipinfo
, &pseudoheader
[0]);
321 memcpy(&pseudoheader
[4], tcb
->tcb_peeraddr
, IP_ADDR_LEN
);
323 pseudoheader
[9] = IPPROTO_TCP
;
324 pseudoheader
[10] = ((tcplen
+hdrlen
) >> 8) & 0xFF;
325 pseudoheader
[11] = ((tcplen
+hdrlen
) & 0xFF);
328 * Checksum the packet and insert the checksum into the header
330 cksum
= ip_chksum(0, pseudoheader
, sizeof(pseudoheader
));
331 cksum
= ip_chksum(cksum
, tcphdr
, tcplen
+ hdrlen
);
333 cksumptr
[0] = (cksum
>> 8) & 0xFF;
334 cksumptr
[1] = (cksum
& 0xFF);
337 * Transmit the packet. The layer below us will free it.
339 _ip_send(ti
->ti_ipinfo
, b
, tcb
->tcb_peeraddr
, IPPROTO_TCP
);
343 * _tcphttp_rx_callback(ref,buf,destaddr,srcaddr)
345 * The IP layer calls this routine when a TCP packet is received.
346 * We dispatch the packet to appropriate handlers from here.
349 * ref - our tcp information (held by the ip stack for us)
350 * buf - the ebuf that we received
351 * destaddr,srcaddr - destination and source IP addresses
354 * ETH_DROP or ETH_KEEP, depending if we keep the packet or not
357 _tcphttp_rx_callback(void *ref
, ebuf_t
*buf
, uint8_t *destaddr
, uint8_t *srcaddr
)
359 uint8_t pseudoheader
[12];
370 http_info_t
*ti
= (http_info_t
*)ref
;
371 tcb_t
*tcb
= &ti
->tcb
;
377 if (httpd_state
.state
== HTTP_NOT_READY
)
380 * get a pointer to the TCP header
382 tcplen
= ebuf_length(buf
);
383 tcphdr
= ebuf_ptr(buf
);
386 * construct the pseudoheader for the cksum calculation
388 memcpy(&pseudoheader
[0], srcaddr
, IP_ADDR_LEN
);
389 memcpy(&pseudoheader
[4], destaddr
, IP_ADDR_LEN
);
391 pseudoheader
[9] = IPPROTO_TCP
;
392 pseudoheader
[10] = (tcplen
>> 8) & 0xFF;
393 pseudoheader
[11] = (tcplen
& 0xFF);
395 origcksum
= ((uint16_t)tcphdr
[16] << 8) | (uint16_t)tcphdr
[17];
396 tcphdr
[16] = tcphdr
[17] = 0;
398 calccksum
= ip_chksum(0, pseudoheader
, sizeof(pseudoheader
));
399 calccksum
= ip_chksum(calccksum
, tcphdr
, tcplen
);
400 calccksum
= ~calccksum
;
401 if (calccksum
!= origcksum
)
404 /* Read the other TCP header fields from the packet */
405 ebuf_get_u16_be(buf
, srcport
);
406 ebuf_get_u16_be(buf
, dstport
);
408 DEBUGMSG(("TCP dport is not 80\n"));
412 ebuf_get_u32_be(buf
, seqnum
);
413 ebuf_get_u32_be(buf
, acknum
);
414 ebuf_get_u16_be(buf
, flags
);
415 ebuf_get_u16_be(buf
, window
);
417 /* skip checksum and urgent pointer */
420 /* Skip options in header */
421 if (TCPHDRSIZE(flags
) < TCP_HDR_LENGTH
)
424 ebuf_skip(buf
, (TCPHDRSIZE(flags
) - TCP_HDR_LENGTH
));
426 switch (tcb
->tcb_state
) {
427 case TCPSTATE_CLOSED
:
428 if (flags
& TCPFLG_SYN
) {
430 if (tcb
->tcb_txbuf
) {
431 tcb
->tcb_txbuf
= NULL
;
434 if (tcb
->tcb_rxbuf
) {
435 KFREE(tcb
->tcb_rxbuf
);
436 tcb
->tcb_rxbuf
= NULL
;
439 tcb
->tcb_txflags
= TCPFLG_SYN
| TCPFLG_ACK
;
440 tcb
->tcb_rcvnext
= seqnum
+ 1;
441 tcb
->tcb_sendnext
= ti
->ti_iss
;
442 tcb
->tcb_lclport
= dstport
;
443 tcb
->tcb_peerport
= srcport
;
444 _tcp_setstate(tcb
, TCPSTATE_SYN_SENT
);
447 memcpy(tcb
->tcb_peeraddr
, srcaddr
, IP_ADDR_LEN
);
449 tcb
->tcb_sendwindow
= 1500;
450 _tcphttp_protosend(ti
, tcb
);
454 case TCPSTATE_SYN_SENT
:
455 if (flags
& TCPFLG_ACK
) {
456 if (tcb
->tcb_rcvnext
!= seqnum
)
457 goto send_ack_nodata
;
459 tt
= tcb
->tcb_sendnext
;
462 tcb
->tcb_sendnext
= tt
;
464 httpd_accept(&httpd_state
, ti
, tcb
);
465 _tcp_setstate(tcb
, TCPSTATE_ESTABLISHED
);
468 else if (flags
& TCPFLG_SYN
)
472 case TCPSTATE_ESTABLISHED
:
473 /* swap src,dst port */
474 if (srcport
!= tcb
->tcb_peerport
) {
477 if (tcb
->tcb_rcvnext
!= seqnum
) {
478 printf("tcb->tcb_rcvnext=%08x seqnum=%08x\n", tcb
->tcb_rcvnext
, seqnum
);
479 goto send_ack_nodata
;
482 tt
= tcb
->tcb_sendnext
;
485 printf("acknum=%x expect=%08x\n", acknum
, tt
);
489 tcb
->tcb_sendnext
= tt
;
493 * Figure out how much we're going to take. This should not
494 * exceed our buffer size because we advertised a window
495 * only big enough to fill our buffer.
497 bp
= ebuf_ptr(buf
); /* pointer to TCP data */
498 tt
= ebuf_remlen(buf
); /* Size of TCP data */
501 tcb
->tcb_rcvnext
+= tt
;
502 tcb
->tcb_rxbuf
= KMALLOC(tt
, 0);
503 memcpy(tcb
->tcb_rxbuf
, bp
, tt
);
505 t
= httpd_appcall(&httpd_state
);
507 tcb
->tcb_txflags
= TCPFLG_ACK
|TCPFLG_FIN
;
509 _tcp_setstate(tcb
, TCPSTATE_FINWAIT_1
);
510 goto send_ack_nodata
;
514 tcb
->wait_ack
= plen
;
515 tcb
->tcb_txflags
= TCPFLG_ACK
;
517 if (tcb
->tcb_state
== TCPSTATE_FINWAIT_1
) {
518 tcb
->tcb_txflags
|= TCPFLG_FIN
;
524 case TCPSTATE_FINWAIT_1
:
526 _tcp_setstate(tcb
, TCPSTATE_CLOSED
);
527 tcb
->tcb_sendnext
= acknum
;
528 tcb
->tcb_txflags
= TCPFLG_RST
;
529 goto send_ack_nodata
;
534 KFREE(tcb
->tcb_rxbuf
);
535 tcb
->tcb_rxbuf
= NULL
;
546 tcb
->tcb_sendwindow
= 0;
548 tcb
->tcb_sendwindow
= 1500;
550 _tcphttp_protosend(ti
, tcb
);
552 if (tcb
->tcb_rxbuf
) {
553 KFREE(tcb
->tcb_rxbuf
);
554 tcb
->tcb_rxbuf
= NULL
;
558 httpd_defercall(&httpd_state
);
563 httpd_accept(struct httpd_state
*hs
, http_info_t
*ti
, tcb_t
*tcb
)
565 memset(hs
, 0, sizeof(*hs
));
567 hs
->state
= HTTP_NOGET
;
574 httpd_flush(struct httpd_state
*hs
)
576 tcb_t
*tcb
= hs
->tcb
;
578 tcb
->tcb_txbuf
= hs
->page_buf
;
579 tcb
->txlen
= hs
->page_len
;
580 _tcp_setstate(tcb
, TCPSTATE_FINWAIT_1
);
584 httpd_appcall(struct httpd_state
*hs
)
586 /* Save receive buffer and length */
587 hs
->uip_appdata
= hs
->tcb
->tcb_rxbuf
;
588 hs
->uip_len
= hs
->tcb
->rxlen
;
589 if (hs
->uip_len
<= 0)
593 case HTTP_UPLOAD_EXE
:
594 return httpd_do_ul(hs
);
597 if (strncmp("POST ", hs
->uip_appdata
, 5) == 0) {
599 if (strncmp("f2", hs
->uip_appdata
+6, 2) == 0) {
600 hs
->state
= HTTP_UPLOAD_EXE
;
604 return httpd_do_ul(hs
);
607 else if (strncmp("GET ", hs
->uip_appdata
, 4) == 0) {
608 if (!strncmp("do", hs
->uip_appdata
+5, 2)) {
609 hs
->state
= HTTP_FUNC
;
613 return httpd_do_cmd(hs
);
617 /* If it isn't a GET, we abort the connection. */
621 /* Send mini-web index page out */
624 "<table border=0 cellpadding=0 cellspacing=0 bgcolor=#306498>\r\n"
625 "<tr><td height=57 width=600>\r\n"
626 "<font face=Arial size=6 color=#ffffff>ASUSTeK - CFE miniWeb Server</font>\r\n"
629 "<form action=f2.htm method=post encType=multipart/form-data>\r\n"
630 "Firmware File \r\n"
631 "<input type=file size=35 name=files>\r\n"
632 "<input type=submit value=Upload><br>\r\n"
634 "<form action=do.htm method=get>\r\n"
635 "<br>Command:<br><a href=do.htm?cmd=reboot>Reboot.</a>\r\n"
636 "<br><a href=do.htm?cmd=nvram+erase>Restore default NVRAM values.</a>\r\n"
638 httpd_page_end(hs
, 0, 0);
649 httpd_defercall(struct httpd_state
*hs
)
651 http_info_t
*ti
= hs
->ti
;
652 tcb_t
*tcb
= hs
->tcb
;
656 char *flashdev
= "flash1.trx";
659 if (hs
->state
== HTTP_UPLOAD_EXE
) {
660 if (hs
->ul_state
== UL_UPDATE
) {
662 tcb
->tcb_sendwindow
= 0;
663 _tcp_setstate(tcb
, TCPSTATE_CLOSED
);
664 tcb
->tcb_txflags
= TCPFLG_RST
;
665 _tcphttp_protosend(ti
, tcb
);
668 ui_get_trx_flashdev(flashdev
);
671 httpd_write_flash(flashdev
, (uint8
*)hs
->load_addr
, hs
->ul_offset
);
673 ui_docommands("reboot");
676 else if (hs
->state
== HTTP_FUNC
) {
678 xprintf("%s command executed\n", hs
->eval
);
679 ui_docommands(hs
->eval
);
681 /* End of doing command */
688 * ul_index[0] : http header end
689 * ul_index[1] : multipart[0] header end
691 static int ul_index
[2];
694 read_ul_headers(struct httpd_state
*hs
)
697 char *ul_header
= hs
->load_addr
;
701 * Gather packets together to overcome the problem
702 * when headers crosses packet boundary.
704 if ((hs
->ul_offset
+ hs
->uip_len
) >= 4096)
707 memcpy(&ul_header
[hs
->ul_offset
], hs
->uip_appdata
, hs
->uip_len
);
708 hs
->ul_offset
+= hs
->uip_len
;
709 ul_header
[hs
->ul_offset
] = 0;
711 /* Search for two <CR><LF><CR><LF> */
713 ul_index
[0] = ul_index
[1] = 0;
714 for (i
= 0; i
< hs
->ul_offset
; i
++) {
717 /* Search end of headers */
718 if (*(end
+0) == ISO_cr
&& *(end
+1) == ISO_nl
&&
719 *(end
+2) == ISO_cr
&& *(end
+3) == ISO_nl
) {
726 if (ul_index
[1] == 0)
733 parse_ul_headers(struct httpd_state
*hs
)
736 char *ul_header
= hs
->load_addr
;
739 for (i
= 0; i
< ul_index
[1]; i
++) {
740 line
= &ul_header
[i
];
742 if (*line
== ISO_cr
|| *line
== ISO_nl
) {
743 /* Null end this line */
748 *line
= *line
| 0x20;
752 /* Get necessary name:value */
753 for (i
= 0; i
< ul_index
[0]; i
++) {
754 line
= &ul_header
[i
];
759 if (!strncmp("content-length:", line
, 15)) {
760 sscanf(line
+15, "%d", &hs
->ul_len
);
768 * Reads one line and decides what to do next.
771 httpd_load_program(struct httpd_state
*hs
)
776 /* Process headers for content-length, and content-type */
777 if (hs
->ul_state
== 0) {
779 * Read http headers and
782 rc
= read_ul_headers(hs
);
787 * Parse http headers to get
788 * content_length and content_type.
790 parse_ul_headers(hs
);
793 /* Copy remaining data to load_addr */
794 hs
->ul_cnt
= hs
->ul_offset
- ul_index
[0];
795 hs
->ul_offset
-= ul_index
[1];
798 * Do memmove from load_addr[i],
799 * where i is the beginning of
803 for (j
= 0; j
< hs
->ul_offset
; j
++)
804 hs
->load_addr
[j
] = hs
->load_addr
[i
+j
];
808 else if (hs
->ul_state
== UL_MULTIPART
) {
809 if ((hs
->ul_offset
+ hs
->uip_len
) > hs
->load_limit
||
810 hs
->ul_cnt
>= hs
->ul_len
) {
815 memcpy(hs
->load_addr
+ hs
->ul_offset
, hs
->uip_appdata
, hs
->uip_len
);
816 hs
->ul_offset
+= hs
->uip_len
;
817 hs
->load_addr
[hs
->ul_offset
] = 0;
819 hs
->ul_cnt
+= hs
->uip_len
;
820 if (hs
->ul_cnt
< hs
->ul_len
)
823 /* Let trx_validate() handle image size */
827 if (hs
->ul_state
== UL_UPDATE
) {
831 "<pre>Receive file size=%d<br><font face=Arial size=5>",
834 * Do trx header check.
836 rc
= trx_validate((uint8_t *)hs
->load_addr
, &hs
->ul_offset
);
839 resp
= "Upload completed. System is going to reboot.<br>Please wait a few moments.";
842 case CFE_ERR_DEVNOTFOUND
:
843 resp
= "Could not open flash device.";
848 resp
= "The file transferred is not a valid firmware image.";
853 httpd_printf(hs
, "%s</font></pre>", resp
);
854 httpd_page_end(hs
, 0, 1);
856 return (rc
== 0 ? 0 : -1);
863 * Parse the command issued by the mini Web
866 httpd_cmd_parse(struct httpd_state
*hs
)
874 /* Work on temp buffer */
875 len
= hs
->uip_len
> sizeof(buf
)-1 ? sizeof(buf
)-1 : hs
->uip_len
;
876 memcpy(buf
, hs
->uip_appdata
, len
);
879 /* process GET do.htm?cmd= */
889 while ((c
= *p
& 0xff) != 0 ) {
895 sscanf(p
+1, "%02x", &c
);
899 * Replace with white space
913 /* Return null command */
918 httpd_printf(struct httpd_state
*hs
, char *templat
, ...)
923 if (hs
->page_len
> sizeof(hs
->page_buf
) - 32)
926 va_start(marker
, templat
);
927 hs
->page_len
+= xvsprintf(hs
->page_buf
+ hs
->page_len
, templat
, marker
);
932 httpd_page_init(struct httpd_state
*hs
)
936 "HTTP/1.1 200 OK\r\n"
937 "Pragma: no-cache\r\nCache-Control: no-cache\r\n"
938 "Connection: close\r\n\r\n"
943 httpd_page_end(struct httpd_state
*hs
, int rc
, int f
)
946 "<!-- Recive file size=%d bytes-->%s</BODY></HTML>\r\n",
947 rc
, f
? "<a href=""/"">Continue</a>" : "");
954 httpd_do_cmd(struct httpd_state
*hs
)
959 cmd
= httpd_cmd_parse(hs
);
960 if (strcmp(cmd
, "reboot") == 0 ||
961 strcmp(cmd
, "nvram erase") == 0) {
963 * Defer these two comands,
964 * until sending response out.
966 strcpy(hs
->eval
, cmd
);
969 rc
= ui_docommands(cmd
);
972 /* Send response out */
974 "<pre><font face=Arial size=5>Command %s completed.</font></pre>",
977 httpd_page_end(hs
, rc
, 1);
982 httpd_do_ul(struct httpd_state
*hs
)
984 uint8_t *load_addr
= NULL
;
986 if (hs
->load_addr
== NULL
) {
988 ui_get_flash_buf(&load_addr
, &hs
->load_limit
);
989 hs
->load_addr
= (char *)load_addr
;
995 if (httpd_load_program(hs
) == -1)
1002 httpd_write_flash(char *flashdev
, uint8
*load_addr
, int len
)
1006 flash_info_t flashinfo
;
1015 * Make sure it's a flash device.
1017 res
= cfe_getdevinfo(flashdev
);
1019 xprintf("Could not find flash device '%s'\n", flashdev
);
1023 devtype
= res
& CFE_DEV_MASK
;
1027 return 0; /* 0 bytes, don't flash */
1030 * Open the destination flash device.
1032 fh
= cfe_open(flashdev
);
1034 xprintf("Could not open device '%s'\n", flashdev
);
1035 return CFE_ERR_DEVNOTFOUND
;
1038 if (cfe_ioctl(fh
, IOCTL_FLASH_GETINFO
, (unsigned char *)&flashinfo
,
1039 sizeof(flash_info_t
), &res
, 0) == 0) {
1040 /* Truncate write if source size is greater than flash size */
1041 if ((copysize
+ offset
) > flashinfo
.flash_size
)
1042 copysize
= flashinfo
.flash_size
- offset
;
1046 * If overwriting the boot flash, we need to use the special IOCTL
1047 * that will force a reboot after writing the flash.
1049 if (flashinfo
.flash_flags
& FLASH_FLAG_INUSE
) {
1050 #if CFG_EMBEDDED_PIC
1052 "\n\n** DO NOT TURN OFF YOUR MACHINE UNTIL THE FLASH UPDATE COMPLETES!! **\n\n");
1055 if (net_getparam(NET_DEVNAME
)) {
1056 xprintf("Closing network.\n");
1059 #endif /* CFG_NETWORK */
1060 xprintf("Rewriting boot flash device '%s'\n", flashdev
);
1061 xprintf("\n\n**DO NOT TURN OFF YOUR MACHINE UNTIL IT REBOOTS!**\n\n");
1062 cfe_ioctl(fh
, IOCTL_FLASH_WRITE_ALL
, load_addr
, copysize
, &retlen
, 0);
1064 /* should not return */
1066 #endif /* EMBEDDED_PIC */
1070 * Otherwise: it's not the flash we're using right
1071 * now, so we can be more verbose about things, and
1072 * more importantly, we can return to the command
1073 * prompt without rebooting!
1077 * Erase the flash, if the device requires it. Our new flash
1078 * driver does the copy/merge/erase for us.
1081 if ((devtype
== CFE_DEV_FLASH
) && !(flashinfo
.flash_flags
& FLASH_FLAG_NOERASE
)) {
1082 flash_range_t range
;
1083 range
.range_base
= offset
;
1084 range
.range_length
= copysize
;
1085 xprintf("Erasing flash...");
1086 if (cfe_ioctl(fh
, IOCTL_FLASH_ERASE_RANGE
, (uint8_t *)&range
,
1087 sizeof(range
), NULL
, 0) != 0) {
1088 xprintf("Failed to erase the flash\n");
1090 return CFE_ERR_IOERR
;
1098 xprintf("Programming...");
1100 amtcopy
= cfe_writeblk(fh
, offset
, load_addr
, copysize
);
1101 if (copysize
== amtcopy
) {
1102 xprintf("done. %d bytes written\n", amtcopy
);
1106 xprintf("Failed. %d bytes written\n", amtcopy
);
1107 res
= CFE_ERR_IOERR
;
1118 trx_validate(uint8_t *ptr
, int *insize
)
1120 struct trx_header
*hdr
= (struct trx_header
*)ptr
;
1122 int32 len
= ltoh32(hdr
->len
);
1123 flash_info_t flashinfo
;
1128 ui_get_trx_flashdev(flashdev
);
1130 char *flashdev
= "flash1.trx";
1133 if (ltoh32(hdr
->magic
) != TRX_MAGIC
) {
1134 xprintf("\nTRX magic number error!");
1139 * Open the destination flash device.
1141 fh
= cfe_open(flashdev
);
1143 xprintf("\nOpen device '%s' failed!", flashdev
);
1144 return CFE_ERR_DEVNOTFOUND
;
1147 cfe_ioctl(fh
, IOCTL_FLASH_GETINFO
, (unsigned char *)&flashinfo
,
1148 sizeof(flash_info_t
), &res
, 0);
1153 if (len
> *insize
||
1154 len
> flashinfo
.flash_size
||
1155 len
< sizeof(struct trx_header
)) {
1156 xprintf("\nTRX file size error!");
1160 calccrc
= flash_crc32(ptr
+ 12, len
-12);
1161 if (calccrc
!= ltoh32(hdr
->crc32
)) {
1162 xprintf("\nTRX CRC error!");
1167 printf("\nTRX file size = %d\n", len
);