summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsave2010-05-06 15:31:22 +0000
committersave2010-05-06 15:31:22 +0000
commita5bdc88adc5544c9a7c218a5762911f2905f59be (patch)
treedc38e8e0b974b60e4027de5a799ebf5e8ca8cbd2
parentc31c0bca66da86bbc3f83dbbaed7f831a662e618 (diff)
cleo/tools/spidupd: re-develop a test application for auto-update, closes #711
git-svn-id: svn+ssh://pessac/svn/cesar/trunk@6988 017c9cb6-072f-447c-8318-d5b54f68fe89
-rw-r--r--cleopatre/tools/spidupd/Makefile43
-rw-r--r--cleopatre/tools/spidupd/spidupd_host.c992
-rw-r--r--cleopatre/tools/spidupd/spidupd_host.h72
3 files changed, 479 insertions, 628 deletions
diff --git a/cleopatre/tools/spidupd/Makefile b/cleopatre/tools/spidupd/Makefile
index 34e764be54..bb4e4e8299 100644
--- a/cleopatre/tools/spidupd/Makefile
+++ b/cleopatre/tools/spidupd/Makefile
@@ -1,38 +1,31 @@
-
+BIN=spidupd_host
DEBUG=no
+#################################
+
CC=gcc
-ifeq ($(DEBUG),yes)
- CFLAGS=-W -Wall -ansi -pedantic -g
- LDFLAGS=
-else
- #CFLAGS=-W -Wall -ansi -pedantic
- LDFLAGS=
-endif
-EXEC=spidupd_host
-SRC= $(wildcard *.c)
-OBJ= $(SRC:.c=.o)
-LDLIBS= -lssl
+CFLAGS=-W -Wall -I. -MMD
+LDFLAGS=
-all: $(EXEC)
ifeq ($(DEBUG),yes)
- @echo "Debug mode generated"
-else
- @echo "Release mode generated"
+ CFLAGS+=-g
endif
-spidupd_host: $(OBJ)
- $(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS)
+SRCS=$(wildcard *.c)
+OBJS=$(SRCS:.c=.o)
+DEPS=$(patsubst %o,%d,$(OBJS))
-%.o: %.c
- $(CC) -o $@ -c $< $(CFLAGS)
+LIBS=-lssl
+
+all: $(BIN)
-spidupd_host.o: spidupd_host.h
+$(BIN): $(OBJS)
+ $(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
-.PHONY: clean mrproper
+%.o: %.c
+ $(CC) $(CFLAGS) -o $@ -c $<
clean:
- @rm -rf *.o spidupd_host
+ rm -rf $(OBJS) $(DEPS) $(BIN)
-mrproper: clean
- @rm -rf $(EXEC)
+-include $(DEPS)
diff --git a/cleopatre/tools/spidupd/spidupd_host.c b/cleopatre/tools/spidupd/spidupd_host.c
index 14ff989742..5b71eed12f 100644
--- a/cleopatre/tools/spidupd/spidupd_host.c
+++ b/cleopatre/tools/spidupd/spidupd_host.c
@@ -17,718 +17,592 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
- *
- * Author(s):
- * Drasko DRASKOVIC, drasko.draskovic@spidcom.com
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <getopt.h>
+#include <linux/types.h>
#include <sys/socket.h>
#include <features.h>
+#include <linux/if.h>
#include <linux/if_packet.h>
#include <linux/if_ether.h>
+#include <arpa/inet.h>
#include <errno.h>
#include <sys/ioctl.h>
-#include <net/if.h>
-#include <net/ethernet.h>
-#include <inttypes.h>
+#include <sys/time.h>
#include "spidupd_host.h"
#include <openssl/md5.h>
#include <unistd.h>
#include "../../u-boot-1.1.6/include/asm/arch-spc300/image_desc.h"
-/** Host PC MAC address */
-#define SRC_ETHER_ADDR "00:11:95:dc:d1:3f"
-/** Board MAC address */
-#define DST_ETHER_ADDR "00:50:c2:38:00:0B"
-
-/** MME Ethertype (SPiDCOM Update) */
-#define PROT_SPIDUPD 0x88E1
-/** server response timeout in seconds */
-#define SRV_CNF_TIMEOUT 1
-/** arbitrary chosen error code for server timeout event */
-#define SRV_TIMEOUT_ERR_CODE -111
-
-/** Number of retries in case of server response timeout */
-#define MAX_TMO_RETRY 5
-/** Wait a little longer for UPDATE_END_CNF, because it takes time to write flash */
-#define MAX_TMO_END_RETRY 120
-/** Number of retries in case of server not ack the package */
-#define MAX_PKT_RETRY 5
-
-/**
- * Convert a byte into a string in hexadecimal.
- * \param str string result
- * \param ptr bytes to convert
- * \param len number of bytes
- * \param delim delimiter inserted between each byte
- */
-static void
-sprintf_hex (unsigned char *str, const unsigned char *ptr,
- int len, unsigned char delim)
-{
- static const unsigned char __hexdigits[] = "0123456789ABCDEF";
- int i, j = 0;
- for (i = 0; i < len; i++)
- {
- if (i)
- str[j++] = delim;
- str[j++] = __hexdigits[ptr[i] >> 4];
- str[j++] = __hexdigits[ptr[i] & 0x0F];
- }
- str[j] = 0;
-}
+#define MAX_RETRY 40
+#define RESTART_TIMEOUT 200000
-/**
- * Set a timeout for the socket connection.
- * \param rawsock socket fd
- * \param milliseconds timeout in ms
- * \return error code
- */
-int
-SetSocketTimeout (int rawsock, int milliseconds)
-{
- struct timeval tv;
-
- tv.tv_sec = milliseconds / 1000;
- tv.tv_usec = (milliseconds % 1000) * 1000;
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
- return setsockopt (rawsock, SOL_SOCKET, SO_RCVTIMEO, (char *) &tv,
- sizeof tv);
+enum rx_status_t
+{
+ RX_OK,
+ RX_WRONG_PKT,
+ RX_TIMEOUT,
+ RX_ERROR,
+ RX_STATUS_NB
+};
+typedef enum rx_status_t rx_status_t;
+
+struct connection_t
+{
+ /** Host MAC address. */
+ unsigned char host_addr[ETH_ALEN];
+ /** Board MAC address. */
+ unsigned char board_addr[ETH_ALEN];
+ /** Socket file descriptor. */
+ int fd;
+};
+typedef struct connection_t connection_t;
+
+struct option long_opts[] = {
+ {"dev", required_argument, NULL, 'd'},
+ {"addr", required_argument, NULL, 'a'},
+ {"file", required_argument, NULL, 'f'},
+};
+
+static inline void
+print_usage (const char *cmd)
+{
+ fprintf(stderr, "Usage : %s\n" \
+ " --dev network device name (eth0...)\n" \
+ " --addr board MAC address\n" \
+ " --file file name\n",
+ cmd);
}
-/**
- * Get the MAC address of a device (eth0...).
- * \param device device name
- * \param rawsock socket fd
- * \param our_addr MAC address result
- * \return error code
- */
-int
-GetMacAddr (char *device, int rawsock, unsigned char our_addr[6])
+static inline void
+convert_mac_str_to_bin (const char *str, unsigned char addr[ETH_ALEN])
{
- int i = 0;
- struct ifreq ifr;
-
- strcpy (ifr.ifr_name, device);
- ioctl (rawsock, SIOCGIFHWADDR, &ifr);
+ int i;
+ char *s, *e;
- for (i = 0; i < 6; i++)
+ s = (char *)str;
+ for (i = 0; i < ETH_ALEN; ++i)
{
- our_addr[i] = (unsigned char) ifr.ifr_hwaddr.sa_data[i];
+ addr[i] = s ? strtoul (s, &e, 16) : 0;
+ if (s)
+ s = (*e) ? e + 1 : e;
}
-
- return 0;
}
-/**
- * Socket creation.
- * \param protocol_to_sniff protocol to sniff
- * \return error code
- */
-int
-CreateRawSocket (int protocol_to_sniff)
+static inline void
+prepare_mme_header (connection_t *connect, unsigned char *pkt,
+ unsigned short mmtype)
{
- int rawsock;
+ MME_t *hdr;
- if ((rawsock =
- socket (PF_PACKET, SOCK_RAW, htons (protocol_to_sniff))) == -1)
- {
- perror ("Error creating raw socket: ");
- exit (-1);
- }
+ hdr = (MME_t *) pkt;
- return rawsock;
+ memcpy (hdr->mme_dest, connect->board_addr, ETH_ALEN);
+ memcpy (hdr->mme_src, connect->host_addr, ETH_ALEN);
+ hdr->mtype = htons (ETH_P_HPAV);
+ hdr->mmv = MME_MMV;
+ hdr->mmtype = htommes (mmtype);
}
-/**
- * Bind a socket.
- * \param device device interface
- * \param rawsock socket fd
- * \param protocol protocol to bind
- * \return error code
- */
-int
-BindRawSocketToInterface (char *device, int rawsock, int protocol)
+static connection_t *
+create_connection (char *dev_name, unsigned char dest_addr[ETH_ALEN])
{
struct sockaddr_ll sll;
struct ifreq ifr;
+ connection_t *connect;
bzero (&sll, sizeof (sll));
bzero (&ifr, sizeof (ifr));
- /* First Get the Interface Index */
- strncpy ((char *) ifr.ifr_name, device, IFNAMSIZ);
- if ((ioctl (rawsock, SIOCGIFINDEX, &ifr)) == -1)
+ /* Create a connection structure. */
+ connect = (connection_t *) malloc (sizeof (connection_t));
+ if (connect == NULL)
+ return NULL;
+
+ /* Create a socket on MME. */
+ if ((connect->fd = socket (AF_PACKET, SOCK_RAW, ETH_P_HPAV)) == -1)
{
- printf ("Error getting Interface index !\n");
- exit (-1);
+ perror ("Error creating raw socket");
+ free (connect);
+ return NULL;
}
+ /* Get the Interface Index. */
+ strncpy ((char *) ifr.ifr_name, dev_name, IFNAMSIZ);
+ if ((ioctl (connect->fd, SIOCGIFINDEX, &ifr)) == -1)
+ {
+ perror ("Error getting Interface index\n");
+ close (connect->fd);
+ free (connect);
+ return NULL;
+ }
- /* Bind our raw socket to this interface */
+ /* Bind socket to this interface index. */
sll.sll_family = AF_PACKET;
sll.sll_ifindex = ifr.ifr_ifindex;
- sll.sll_protocol = htons (protocol);
-
+ sll.sll_protocol = htons (ETH_P_HPAV);
- if ((bind (rawsock, (struct sockaddr *) &sll, sizeof (sll))) == -1)
+ if ((bind (connect->fd, (struct sockaddr *) &sll, sizeof (sll))) == -1)
{
perror ("Error binding raw socket to interface\n");
- exit (-1);
+ close (connect->fd);
+ free (connect);
+ return NULL;
}
- return 1;
-}
-
-/**
- * Send a packet.
- * \param rawsock socket fd
- * \param pkt packet to send
- * \param pkt_len packet length
- * \return error code
- */
-int
-SendRawPacket (int rawsock, unsigned char *pkt, int pkt_len)
-{
- int sent = 0;
-
- /* A simple write on the socket ..thats all it takes ! */
- if ((sent = write (rawsock, pkt, pkt_len)) != pkt_len)
+ /* Get host MAC address. */
+ if ((ioctl (connect->fd, SIOCGIFHWADDR, &ifr)) == -1)
{
- /* Error */
- printf ("Could only send %d bytes of packet of length %d\n", sent,
- pkt_len);
- return 0;
+ perror ("Error getting Interface MAC address\n");
+ close (connect->fd);
+ free (connect);
+ return NULL;
}
- return 1;
+ /* Fill MAC addresses. */
+ memcpy (connect->host_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
+ memcpy (connect->board_addr, dest_addr, ETH_ALEN);
+
+ return connect;
}
-/**
- * Create an Ethernet header.
- * \param pkt buffer for header result
- * \param src_mac MAC address source
- * \param dst_mac MAC address destination
- * \param protocol Ethernet type
- */
-void
-CreateEthernetHeader (unsigned char *pkt, char *src_mac, char *dst_mac,
- int protocol)
+static inline void
+close_connection (connection_t *connect)
{
- struct ethhdr *ethernet_header;
-
- ethernet_header = (struct ethhdr *) pkt;
-
- /* copy the Src mac addr */
- memcpy (ethernet_header->h_source, (void *) ether_aton (src_mac), 6);
-
- /* copy the Dst mac addr */
- memcpy (ethernet_header->h_dest, (void *) ether_aton (dst_mac), 6);
-
- /* copy the protocol */
- ethernet_header->h_proto = htons (protocol);
+ close (connect->fd);
+ free (connect);
}
-/**
- * Print a packet
- * \param packet packet to print
- * \param len length to print
- */
-void
-PrintPacketInHex (unsigned char *packet, int len)
+static int
+get_image_descriptor (char *file, spidcom_image_desc_t *desc)
{
- unsigned char *p = packet;
+ FILE *img_file;
+ ssize_t read_bytes;
- printf ("\n\n---------Packet---Starts----\n\n");
+ /* Open image file. */
+ img_file = fopen (file, "r");
- while (len--)
+ /* Copy only the descriptor. */
+ if ((read_bytes = fread (desc, 1, sizeof (spidcom_image_desc_t),
+ img_file)) != sizeof (spidcom_image_desc_t))
{
- printf ("%.2x ", *p);
- p++;
+ perror ("fread failed check your file");
+ fclose (img_file);
+ return -1;
}
- printf ("\n\n--------Packet---Ends-----\n\n");
-
-}
-
-void
-PrintInHex (char *mesg, unsigned char *p, int len)
-{
- printf (mesg);
-
- while (len--)
+ /* Check file header magic word. */
+ if (strcmp (desc->magic, SPIDCOM_IMG_DESC_MAGIC))
{
- printf ("%.2X ", *p);
- p++;
+ printf ("Error %s isn't a correct image\n", file);
+ fclose (img_file);
+ return -1;
}
+ return 0;
}
-/**
- * Ethernet header parser
- * \param packet packet to parse
- * \param len length to parse
- */
-void
-ParseEthernetHeader (unsigned char *packet, int len)
+static int
+send_packet (connection_t *connect, void *pkt, ssize_t len)
{
- struct ethhdr *ethernet_header;
-
- if (len > sizeof (struct ethhdr))
- {
- ethernet_header = (struct ethhdr *) packet;
-
- /* First set of 6 bytes are Destination MAC */
-
- PrintInHex ("Destination MAC: ", ethernet_header->h_dest, 6);
- printf ("\n");
-
- /* Second set of 6 bytes are Source MAC */
-
- PrintInHex ("Source MAC: ", ethernet_header->h_source, 6);
- printf ("\n");
-
- /* Last 2 bytes in the Ethernet header are the protocol it carries */
-
- PrintInHex ("Protocol: ", (void *) &ethernet_header->h_proto, 2);
- printf ("\n");
+ ssize_t sent;
+ /* Send the packet. */
+ sent = send (connect->fd, pkt, len, 0);
+ /* Error with send procedure. */
+ if (sent < 0)
+ {
+ perror ("Error sending a packet");
+ return -1;
}
- else
+
+ /* Error with sent length. */
+ if (sent != len)
{
- printf ("Packet size too small !\n");
+ printf ("Can only sent %d bytes but expected %d\n", sent, len);
+ return -1;
}
+
+ return 0;
}
-/**
- * Listern on socket.
- * \param raw socket to listen
- * \return error code
- */
-int
-ListenSocket (int raw)
+static rx_status_t
+receive_packet (connection_t *connect, void *pkt,
+ size_t max_len, unsigned long timeout, unsigned int type)
{
- unsigned char *packet_buffer, *pkt_start;
- int len;
- struct sockaddr_ll packet_info;
- int packet_info_size = sizeof (packet_info);
- MME_t *s;
int res;
+ MME_t *hdr;
+ fd_set read_to;
+ struct timeval restart_to;
+ struct sockaddr_ll packet_info;
+ socklen_t packet_info_size = sizeof (packet_info);
- fd_set readset;
- struct timeval srv_cnf_timeout;
-
- int rc;
-
- MsUpdStartCnf_t *ms_update_start_cnf;
- MsUpdTransfCnf_t *ms_update_transfer_cnf;
- MsUpdEndCnf_t *ms_update_end_cnf;
-
- packet_buffer = (unsigned char *) calloc (PKTSIZE, sizeof (char));
- pkt_start = packet_buffer;
+ /* Prepare timeout. */
+ FD_ZERO (&read_to);
+ FD_SET (connect->fd, &read_to);
+ restart_to.tv_sec = 0;
+ restart_to.tv_usec = timeout;
- /* check for socket timeout */
- FD_ZERO (&readset);
- FD_SET (raw, &readset);
- srv_cnf_timeout.tv_sec = SRV_CNF_TIMEOUT;
- srv_cnf_timeout.tv_usec = 0;
+ /* Wait reception with timeout. */
+ res = select (connect->fd + 1, &read_to, NULL, NULL, &restart_to);
- /* readset fd_set is containing only our socket, so no need to check with FD_ISSET() */
- res = select (raw + 1, &readset, NULL, NULL, &srv_cnf_timeout);
+ /* Error with waiting procedure. */
if (res < 0)
{
- perror ("select() failed");
+ perror ("select failed");
+ return RX_ERROR;
}
- else if (res == 0) /* timeout */
+
+ /* Wait until timeout. */
+ else if (res == 0)
{
- //printf("Server response timeout.\n");
- rc = SRV_TIMEOUT_ERR_CODE;
+ return RX_TIMEOUT;
}
- else /* everything is cool, socket is ready for reading */
- {
- if ((len =
- recvfrom (raw, packet_buffer, PKTSIZE, 0,
- (struct sockaddr *) &packet_info,
- &packet_info_size)) < 0)
- {
- perror ("Recv from returned error: ");
- exit (-1);
- }
- else
+ /* Receive a packet before timeout. */
+ else
+ {
+ /* Get the receive packet. */
+ if (recvfrom (connect->fd, pkt, max_len, 0,
+ (struct sockaddr *) &packet_info,
+ &packet_info_size) < 0)
{
- /* Packet has been received successfully !! */
- //PrintPacketInHex(packet_buffer, len);
+ /* Reception error. */
+ perror ("recvfrom failed");
+ return RX_ERROR;
}
- s = (MME_t *) packet_buffer;
- packet_buffer += MME_HDR_SIZE;
-
- switch (mmetohs (s->mmtype))
+ /* Check that the received packet is the expected. */
+ hdr = (MME_t *) pkt;
+ if (mmetohs (hdr->mmtype) != type)
{
- case MS_UPDATE_START_CNF:
- ms_update_start_cnf = (MsUpdStartCnf_t *) packet_buffer;
- rc = ms_update_start_cnf->start_update;
- break;
-
- case MS_UPDATE_TRANSFER_CNF:
- ms_update_transfer_cnf = (MsUpdTransfCnf_t *) packet_buffer;
- rc = ms_update_transfer_cnf->ack;
- break;
-
- case MS_UPDATE_END_CNF:
- ms_update_end_cnf = (MsUpdEndCnf_t *) packet_buffer;
- rc = ms_update_end_cnf->result;
- break;
-
- deafault:
- break;
+ return RX_WRONG_PKT;
}
}
-
- return rc;
+ return RX_OK;
}
-/**
- * Main program.
- * \param argc number of arguments
- * \param argv argument list
- * \return error code
- *
- * argv[1] is the device e.g. eth0
- */
-int
-main (int argc, char **argv)
+static int
+connect_to_server (connection_t *connect, spidcom_image_desc_t *desc)
{
- int raw;
- unsigned char *packet;
- unsigned char *pkt_start;
- int ethhdr_len;
- int pkt_len = 0;
- int data_len = 0;
- unsigned char our_mac[6];
- unsigned char our_mac_string[18];
- unsigned char board_mac_string[18];
- MME_t *s;
- unsigned char tmp_buffer[SPIDUPD_BLOCK_SIZE];
- FILE *pImgFile;
- int block_counter = 0;
- unsigned char md5_sum[16];
- MD5_CTX ctx;
- int read_bytes;
- int i;
- int pkt_retry = 0;
- int tmo_retry = 0;
- int res;
- spidcom_image_desc_t desc;
-
- static MsUpdStartReq_t *ms_update_start_req;
- static MsUpdTransfReq_t *ms_update_transfer_req;
- static MsUpdEndReq_t *ms_update_end_req;
-
- if (argc != 3)
+ int result = -1;
+ unsigned char *tx_pkt;
+ unsigned char *rx_pkt;
+ ssize_t tx_pkt_len;
+ rx_status_t rx_status;
+ VsUpdStartReq_t *start_req;
+ VsUpdStartCnf_t *start_cnf;
+ unsigned long retry;
+
+ /* Allocate TX and RX buffers for Request and Confirm MME exchange. */
+ tx_pkt = (unsigned char *) malloc (PKTSIZE);
+ rx_pkt = (unsigned char *) malloc (PKTSIZE);
+ start_req = (VsUpdStartReq_t *) (tx_pkt + sizeof (MME_t));
+ start_cnf = (VsUpdStartCnf_t *) (rx_pkt + sizeof (MME_t));
+
+ /* Prepare START_REQ MME to send to the server. */
+ prepare_mme_header (connect, tx_pkt, VS_UPDATE_START_REQ);
+
+ memcpy (start_req->version, desc->version, sizeof (desc->version));
+ start_req->arch = desc->arch;
+ start_req->upd_type = desc->type;
+ tx_pkt_len = sizeof (MME_t) + sizeof (VsUpdStartReq_t);
+
+ /* Start connection procedure. */
+ for (retry = 0 ; retry < MAX_RETRY ; retry++)
{
- perror ("Wrong parameters: spidupd_test <iface> <img_name>");
- exit (1);
- }
-
- /* Create the raw socket */
- raw = CreateRawSocket (ETH_P_ALL);
-
- /* Bind raw socket to interface */
- BindRawSocketToInterface (argv[1], raw, ETH_P_ALL);
-
- /* create Ethernet header */
- GetMacAddr (argv[1], raw, our_mac);
- sprintf_hex (our_mac_string, our_mac, 6, ':');
- //strcpy(board_mac_string, (const char *)argv[2]);
-
- /* allocate packet */
- packet = (unsigned char *) calloc (PKTSIZE, sizeof (char));
-
- /* record the start position of the packet pointer */
- pkt_start = packet;
-
- //CreateEthernetHeader(packet, our_mac_string, board_mac_string, PROT_SPIDUPD);
- CreateEthernetHeader (packet, SRC_ETHER_ADDR, DST_ETHER_ADDR,
- PROT_SPIDUPD);
- ethhdr_len = sizeof (struct ethhdr);
-
- /* zero-ot image descriptor struct */
- memset (&desc, 0, sizeof (spidcom_image_desc_t));
-
- /* file image desc struct */
- //pImgFile = fopen("linux-kernel-2.6.25.10-arm", "r");
- pImgFile = fopen (argv[2], "r");
-
- read_bytes = fread (&desc, 1, sizeof (spidcom_image_desc_t), pImgFile);
-
- /* --- MESSAGES --- */
-
- /*
- * MS_UPDATE_START_REQ
- */
- s = (MME_t *) packet;
- s->mmv = MME_MMV;
- s->mmtype = htommes (MS_UPDATE_START_REQ);
-
- s++; /*skip the header */
- packet = (unsigned char *) s;
-
- ms_update_start_req = (MsUpdStartReq_t *) packet;
- memcpy (ms_update_start_req->version, (&desc)->version,
- sizeof ((&desc)->version));
- ms_update_start_req->arch = (&desc)->arch;
- ms_update_start_req->upd_type = (&desc)->type;
-
- /* go to the end of message... */
- packet += sizeof (MsUpdStartReq_t);
-
- /*Detertermine total packet length */
- pkt_len = packet - pkt_start;
-
- /* Position packet pointer to strt of the packet */
- packet = pkt_start;
+ /* Send START_REQ MME. */
+ if (send_packet (connect, tx_pkt, tx_pkt_len))
+ break;
+ /* Wait START_CNF MME. */
+ rx_status = receive_packet (connect, rx_pkt, PKTSIZE, RESTART_TIMEOUT,
+ VS_UPDATE_START_CNF);
- /* if packet is not acknowledged ot it is timed out,
- * try several times to re-send same packet */
- printf ("Requesting update start... ");
- fflush (stdout);
- tmo_retry = MAX_TMO_RETRY;
- //while (tmo_retry > 0)
- /* correction - client waits with infinite timeout */
- while (1)
- {
- if (!SendRawPacket (raw, packet, pkt_len))
+ /* We receive a good packet. */
+ if (rx_status == RX_OK)
{
- perror ("Error sending packet");
+ /* Check the server response and quit whatever the answer. */
+ if (start_cnf->start_update == SPIDUPD_SUCCESS)
+ result = 0;
+ else
+ printf ("Cannot start Update procedure (error=%d)\n",
+ start_cnf->start_update);
+ break;
}
- else
- //printf("Requested update start...");
- if ((res = ListenSocket (raw)) == SRV_TIMEOUT_ERR_CODE)
- {
- //tmo_retry--;
- continue;
- }
- else if (res != SPIDUPD_SUCCESS)
- {
- printf ("Error - Cannot start update.\n");
- exit (-1);
- }
- else /* success */
- {
- printf ("OK\n");
+ /* There was an internal error during reception. Stop all. */
+ else if (rx_status == RX_ERROR)
break;
- }
+
+ /* We have received a wrong packet or a timeout.
+ * Send the START_REQ MME again. */
+ else
+ continue;
}
- if (tmo_retry == 0)
+ free (tx_pkt);
+ free (rx_pkt);
+ return result;
+}
+
+static int
+upload_to_server (connection_t *connect, char *file_name,
+ unsigned char *md5_sum)
+{
+ int result;
+ unsigned char *tx_pkt;
+ unsigned char *rx_pkt;
+ ssize_t tx_pkt_min_len;
+ ssize_t tx_pkt_data_len;
+ rx_status_t rx_status;
+ MD5_CTX ctx;
+ FILE *img;
+ VsUpdTransfReq_t *transfer_req;
+ VsUpdTransfCnf_t *transfer_cnf;
+ unsigned long block_counter = 0;
+ unsigned long retry;
+
+ /* Open the image to upload. */
+ if ((img = fopen (file_name, "r")) == NULL)
{
- printf ("\nTimeout error : no response from the server.\n");
- exit (-1);
+ perror ("open image file failed");
+ return -1;
}
- /*
- * MS_UPDATE_TRANSFER_REQ
- */
- rewind (pImgFile);
- read_bytes = fread (tmp_buffer, 1, SPIDUPD_BLOCK_SIZE, pImgFile);
+ /* Allocate TX and RX buffers for Request and Confirm MME exchange. */
+ tx_pkt = (unsigned char *) malloc (PKTSIZE);
+ rx_pkt = (unsigned char *) malloc (PKTSIZE);
+ transfer_req = (VsUpdTransfReq_t *) (tx_pkt + sizeof (MME_t));
+ transfer_cnf = (VsUpdTransfCnf_t *) (rx_pkt + sizeof (MME_t));
- /* init md5 context before we start calculating md5_sum
- * we will need md5 sum to send in the end */
- MD5_Init (&ctx);
+ /* Prepare TRANSFER_REQ MME header. */
+ prepare_mme_header (connect, tx_pkt, VS_UPDATE_TRANSFER_REQ);
+ tx_pkt_min_len = sizeof (MME_t) + sizeof (VsUpdTransfReq_t) - sizeof (transfer_req->data);
- printf ("Uploading Linux image :\n");
+ /* Prepare MD5 image calculation. */
+ MD5_Init (&ctx);
- do
+ /* Read image file block by block. */
+ while ((tx_pkt_data_len = fread (transfer_req->data, 1,
+ SPIDUPD_BLOCK_SIZE, img)) > 0)
{
- /* We are about to send new block */
- block_counter++;
-
- /* reset packet data, but keep the eth header */
- packet = pkt_start;
- memset (packet + ethhdr_len, 0, PKTSIZE - ethhdr_len);
- /* form new message */
- s = (MME_t *) packet;
- s->mmv = MME_MMV;
- s->mmtype = htommes (MS_UPDATE_TRANSFER_REQ);
+ /* Calculate MD5. */
+ MD5_Update (&ctx, transfer_req->data, tx_pkt_data_len);
- s++; /*skip the header */
- packet = (unsigned char *) s;
+ /* Finish TRANSFER_REQ MME to send. */
+ transfer_req->block_id = htommel (++block_counter);
+ transfer_req->length = htommel (tx_pkt_data_len);
- ms_update_transfer_req = (MsUpdTransfReq_t *) packet;
- ms_update_transfer_req->block_id = htommel (block_counter);
- ms_update_transfer_req->length = htommel (read_bytes);
+ /* Show upload progression. */
+ if ((block_counter % 50) == 0)
+ printf (".");
- for (i = 0; i < read_bytes; i++)
+ /* Try to send the block. */
+ for (result = -1, retry = 0 ; retry < MAX_RETRY ; retry++)
{
- ms_update_transfer_req->data[i] = tmp_buffer[i];
- }
-
- /* update md5 context */
- MD5_Update (&ctx, ms_update_transfer_req->data, read_bytes);
-
-
- /* go to the end of message... */
- packet += MME_HDR_SIZE + 2 * sizeof (int) + read_bytes;
-
- /*Detertermine total packet length */
- pkt_len = packet - pkt_start;
+ /* Send TRANSFER_REQ MME. */
+ if (send_packet (connect, tx_pkt,
+ tx_pkt_min_len + tx_pkt_data_len))
+ break;
- /* Position packet pointer to strt of the packet */
- packet = pkt_start;
+ /* Wait TRANSFER MME. */
+ rx_status = receive_packet (connect, rx_pkt, PKTSIZE,
+ RESTART_TIMEOUT,
+ VS_UPDATE_TRANSFER_CNF);
- /* if packet is not acknowledged ot it is timed out,
- * try several times to re-send same packet */
- tmo_retry = MAX_TMO_RETRY;
- pkt_retry = MAX_PKT_RETRY;
- while ((tmo_retry > 0) && (pkt_retry > 0))
- {
- if (!SendRawPacket (raw, packet, pkt_len))
+ /* We receive a good packet. */
+ if (rx_status == RX_OK)
{
- perror ("Error sending packet");
- }
- else
- {
- if ((block_counter % 50) == 0)
+ /* Check the server response. */
+ if (transfer_cnf->ack == SPIDUPD_SUCCESS)
{
- printf ("#");
- fflush (stdout);
+ result = 0;
+ break;
}
-
- if ((block_counter % 2500) == 0)
+ /* Error on server with the last transfer, restart it. */
+ else if (transfer_cnf->next_block == block_counter)
+ continue;
+ /* Error on server with another transfer. Stop upload. */
+ else
{
- putchar ('\n');
- fflush (stdout);
+ printf ("Error on server during block %d transfer\n",
+ transfer_cnf->next_block);
+ break;
}
}
- if ((res = ListenSocket (raw)) == SRV_TIMEOUT_ERR_CODE)
- {
- tmo_retry--;
- continue;
- }
- else if (res != SPIDUPD_SUCCESS)
- {
- printf ("Packet not acknowledged. ");
-
- pkt_retry--;
- continue;
- }
- else /* success */
- {
+ /* There was an internal error during reception. Stop all. */
+ else if (rx_status == RX_ERROR)
break;
- }
- }
-
- if (tmo_retry == 0)
- {
- printf ("timeout error : no response from the server.\n");
- exit (-1);
- }
- if (pkt_retry == 0)
- {
- printf ("Maximum number of packet retries exceeded.\n");
- exit (-1);
+ /* We have received a wrong packet or a timeout.
+ * Send the START_REQ MME again. */
+ else
+ continue;
}
-
+ if (result)
+ break;
}
- while ((read_bytes =
- fread (tmp_buffer, 1, SPIDUPD_BLOCK_SIZE, pImgFile)) > 0);
-
- printf ("\nDone.\n");
- /* Get final md5 */
+ /* Finish MD5 image calculation. */
MD5_Final (md5_sum, &ctx);
- fclose (pImgFile);
-
-
- /*
- * MS_UPDATE_END_REQ
- */
+ free (tx_pkt);
+ free (rx_pkt);
+ fclose (img);
+ return result;
+}
- /* reset packet data, but keep the eth header */
- packet = pkt_start;
- memset (packet + ethhdr_len, 0, PKTSIZE - ethhdr_len);
- /* form new message */
- s = (MME_t *) packet;
- s->mmv = MME_MMV;
- s->mmtype = htommes (MS_UPDATE_END_REQ);
+static int
+disconnect_from_server (connection_t *connect, unsigned char *md5_sum)
+{
+ int result = -1;
+ unsigned char *tx_pkt;
+ unsigned char *rx_pkt;
+ ssize_t tx_pkt_len;
+ rx_status_t rx_status;
+ VsUpdEndReq_t *end_req;
+ VsUpdEndCnf_t *end_cnf;
+ unsigned long retry;
+
+ /* Allocate TX and RX buffers for Request and Confirm MME exchange. */
+ tx_pkt = (unsigned char *) malloc (PKTSIZE);
+ rx_pkt = (unsigned char *) malloc (PKTSIZE);
+ end_req = (VsUpdEndReq_t *) (tx_pkt + sizeof (MME_t));
+ end_cnf = (VsUpdEndCnf_t *) (rx_pkt + sizeof (MME_t));
+
+ /* Prepare END_REQ MME to send to the server. */
+ prepare_mme_header (connect, tx_pkt, VS_UPDATE_END_REQ);
+
+ memcpy (end_req->md5_sum, md5_sum, MD5_DIGEST_LENGTH);
+ tx_pkt_len = sizeof (MME_t) + sizeof (VsUpdEndReq_t);
+
+ /* Stop connection procedure. */
+ for (retry = 0 ; retry < MAX_RETRY ; retry++)
+ {
+ /* Send END_REQ MME. */
+ if (send_packet (connect, tx_pkt, tx_pkt_len))
+ break;
- s++; /* skip the header */
- packet = (unsigned char *) s;
+ /* Wait END_CNF MME. */
+ rx_status = receive_packet (connect, rx_pkt, PKTSIZE, RESTART_TIMEOUT,
+ VS_UPDATE_END_CNF);
- ms_update_end_req = (MsUpdEndReq_t *) packet;
- memcpy (ms_update_end_req->md5_sum, md5_sum, 16);
+ /* We receive a good packet. */
+ if (rx_status == RX_OK)
+ {
+ /* Check the server response and quit whatever the answer. */
+ if (end_cnf->result == SPIDUPD_SUCCESS)
+ result = 0;
+ else
+ printf ("Error on server during end procedure (error=%d)\n",
+ end_cnf->result);
+ break;
+ }
+ /* There was an internal error during reception. Stop all. */
+ else if (rx_status == RX_ERROR)
+ break;
- /* go to the end of message... */
- packet += sizeof (MsUpdEndReq_t);
+ /* We have received a wrong packet or a timeout.
+ * Send the END_REQ MME again. */
+ else
+ continue;
+ }
- /* Detertermine total packet length */
- pkt_len = packet - pkt_start;
+ free (tx_pkt);
+ free (rx_pkt);
+ return result;
+}
- /* Position packet pointer to strt of tyhe packet,
- * and send the packet */
- packet = pkt_start;
+int
+main (int argc, char **argv)
+{
+ int c, opt_index = 0;
+ char device_name[16];
+ char file_name[PATH_MAX];
+ unsigned char board_addr[ETH_ALEN];
+ connection_t *connect;
+ unsigned char md5_sum[MD5_DIGEST_LENGTH];
+ spidcom_image_desc_t desc;
- /* if packet is not timed-out try several times to re-send same packet */
- printf ("Waiting on the server to burn image on flash :\n");
- fflush (stdout);
- tmo_retry = MAX_TMO_END_RETRY;
- while (tmo_retry > 0)
+ /* Check arguments. */
+ if (((argc - 1) / 2) != ARRAY_SIZE(long_opts))
{
- if (!SendRawPacket (raw, packet, pkt_len))
- {
- perror ("Error sending packet");
- }
- else
- //printf ("UPD_END_REQ sent : ");
-
+ print_usage (argv[0]);
+ return -1;
+ }
- if ((res = ListenSocket (raw)) == SRV_TIMEOUT_ERR_CODE)
- {
- printf (">");
- fflush (stdout);
- tmo_retry--;
- continue;
- }
- else if (res != SPIDUPD_SUCCESS)
- {
- printf ("Error - Cannot finish update.\n");
- exit (-1);
- }
- else /* success */
+ /* Analyse arguments. */
+ while ((c = getopt_long_only (argc, argv, "", long_opts,
+ &opt_index)) != -1)
+ {
+ switch (c)
{
- printf ("| Done.\n");
+ case 'd':
+ /* Store device name. */
+ strcpy (device_name, optarg);
+ break;
+ case 'a':
+ /* Store board MAC address. */
+ convert_mac_str_to_bin (optarg, board_addr);
+ break;
+ case 'f':
+ /* Store file name to upload. */
+ strcpy (file_name, optarg);
break;
+ default:
+ print_usage (argv[0]);
+ exit (1);
}
}
- if (tmo_retry == 0)
+ /* Create + bind connection on asked network device. */
+ connect = create_connection (device_name, board_addr);
+ if (connect == NULL)
+ return -1;
+
+ /* Find Image header for upload informations. */
+ if (get_image_descriptor (file_name, &desc))
{
- printf ("Timeout error : no response from the server.\n");
- exit (-1);
+ close_connection (connect);
+ return -1;
}
- /* if we came this far, image was well updated */
- printf ("\nImage has been sucesfully updated.\n\n");
-
- /* --- END OF MESSAGES --- */
+ printf ("Connect to server...\n");
+ if (connect_to_server (connect, &desc))
+ {
+ close_connection (connect);
+ return -1;
+ }
+ printf ("done\n");
- /* Free the ethernet_header back to the heavenly heap */
- free (packet);
+ printf ("Upload image...\n");
+ if (upload_to_server (connect, file_name, md5_sum))
+ {
+ close_connection (connect);
+ return -1;
+ }
+ printf ("done\n");
- close (raw);
+ printf ("Disconnect from server...\n");
+ if (disconnect_from_server (connect, md5_sum))
+ {
+ close_connection (connect);
+ return -1;
+ }
+ printf ("done\n");
+ close_connection (connect);
return 0;
}
+
diff --git a/cleopatre/tools/spidupd/spidupd_host.h b/cleopatre/tools/spidupd/spidupd_host.h
index b2571bde28..b4ca459947 100644
--- a/cleopatre/tools/spidupd/spidupd_host.h
+++ b/cleopatre/tools/spidupd/spidupd_host.h
@@ -17,9 +17,6 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
- *
- * Author(s):
- * Drasko DRASKOVIC, drasko.draskovic@spidcom.com
*/
#ifndef __SPIDUPD_HOST_H__
@@ -32,18 +29,17 @@ struct MME_t
unsigned char mme_dest[6];
/** Source node. */
unsigned char mme_src[6];
- /** ieee 802.1q VLAN tag (optional). */
- //unsigned int vlan_tag;
/** 0x88e1 (iee assigned Ethertype). */
unsigned short mtype;
/** Management Message Version. */
unsigned char mmv;
/** Management Message Type. */
unsigned short mmtype;
- /** Fragmentation Management Info. */
- //unsigned short fmi;
} __attribute__ ((__packed__));
-typedef MME_t MME_t;
+typedef struct MME_t MME_t;
+
+/** Ethernet Type for MMEs. */
+#define ETH_P_HPAV 0x88e1
/** MME header size (Homeplug AV). */
#define MME_HDR_SIZE 17
@@ -79,21 +75,21 @@ typedef MME_t MME_t;
#endif
/** SPIDUPD Messages. */
-#define MS_UPDATE_START 0x8000
-#define MS_UPDATE_TRANSFER 0x8004
-#define MS_UPDATE_END 0x8008
+#define VS_UPDATE_START 0x8000
+#define VS_UPDATE_TRANSFER 0x8004
+#define VS_UPDATE_END 0x8008
/** Informations about REQ, CNF IND or RSP is held in two LSBs. */
-#define MS_UPDATE_START_REQ (MS_UPDATE_START | 0x0)
-#define MS_UPDATE_START_CNF (MS_UPDATE_START | 0x1)
-#define MS_UPDATE_TRANSFER_REQ (MS_UPDATE_TRANSFER | 0x0)
-#define MS_UPDATE_TRANSFER_CNF (MS_UPDATE_TRANSFER | 0x1)
-#define MS_UPDATE_END_REQ (MS_UPDATE_END | 0x0)
-#define MS_UPDATE_END_CNF (MS_UPDATE_END | 0x1)
-#define MS_UPDATE_END_IND (MS_UPDATE_END | 0x2)
+#define VS_UPDATE_START_REQ (VS_UPDATE_START | 0x0)
+#define VS_UPDATE_START_CNF (VS_UPDATE_START | 0x1)
+#define VS_UPDATE_TRANSFER_REQ (VS_UPDATE_TRANSFER | 0x0)
+#define VS_UPDATE_TRANSFER_CNF (VS_UPDATE_TRANSFER | 0x1)
+#define VS_UPDATE_END_REQ (VS_UPDATE_END | 0x0)
+#define VS_UPDATE_END_CNF (VS_UPDATE_END | 0x1)
+#define VS_UPDATE_END_IND (VS_UPDATE_END | 0x2)
/** SPIDUPD Start Request format. */
-struct MsUpdStartReq_t
+struct VsUpdStartReq_t
{
/** version string of the fw to send */
unsigned char version[16];
@@ -102,18 +98,18 @@ struct MsUpdStartReq_t
/** update type; default: 0 for normal image */
unsigned char upd_type;
} __attribute__ ((__packed__));
-typedef MsUpdStartreq_t MsUpdStartreq_t;
+typedef struct VsUpdStartReq_t VsUpdStartReq_t;
/** SPIDUPD Start Confirm format. */
-struct MsUpdStartCnf_t
+struct VsUpdStartCnf_t
{
/** 0 - success, 0x1..0x5 - error messages */
unsigned char start_update;
} __attribute__ ((__packed__));
-typedef struct MsUpdStartCnf_t MsUpdStartCnf_t;
+typedef struct VsUpdStartCnf_t VsUpdStartCnf_t;
/** SPIDUPD Transfer Request format. */
-struct MsUpdTransfReq_t
+struct VsUpdTransfReq_t
{
/** block ID of data to be sent */
unsigned int block_id;
@@ -122,41 +118,41 @@ struct MsUpdTransfReq_t
/** padded data (for min size of eth packet) */
unsigned char data[MAX_MME_SIZE - 8];
} __attribute__ ((__packed__));
-typedef struct MsUpdTransfReq_t MsUpdTransfReq_t;
+typedef struct VsUpdTransfReq_t VsUpdTransfReq_t;
/** SPIDUPD Transfer Confirm format. */
-struct MsUpdTransfCnf_t
+struct VsUpdTransfCnf_t
{
/** 0 - success, 0x1 - failure */
unsigned char ack;
/** next block ID that server expects */
unsigned int next_block;
} __attribute__ ((__packed__));
-typedef struct MsUpdTransfCnf_t MsUpdTransfCnf_t;
+typedef struct VsUpdTransfCnf_t VsUpdTransfCnf_t;
/** SPIDUPD End Request format. */
-struct MsUpdEndReq_t
+struct VsUpdEndReq_t
{
/** 0 - success, 0x1 - failure */
unsigned char md5_sum[16];
} __attribute__ ((__packed__));
-typedef struct MsUpdEndReq_t MsUpdEndReq_t;
+typedef struct VsUpdEndReq_t VsUpdEndReq_t;
/** SPIDUPD End Confirm format. */
-struct MsUpdEndCnf_t
+struct VsUpdEndCnf_t
{
/** 0 - success, 0x1 - failure */
unsigned char result;
} __attribute__ ((__packed__));
-typedef struct MsUpdEndCnf_t MsUpdEndCnf_t;
+typedef struct VsUpdEndCnf_t VsUpdEndCnf_t;
/** SPIDUPD End Indication format. */
-struct MsUpdEndInd_t
+struct VsUpdEndInd_t
{
/** 0 - success, 0x1..0x2 - error messages */
unsigned char result;
} __attribute__ ((__packed__));
-typedef struct MsUpdEndInd_t MsUpdEndInd_t;
+typedef struct VsUpdEndInd_t VsUpdEndInd_t;
/** Failure codes in server response
* start_cnf */
@@ -180,16 +176,4 @@ typedef struct MsUpdEndInd_t MsUpdEndInd_t;
* end_ind */
#define SPIDUPD_FLASH_WRITE_TOUT 0x02
-/** define an address in RAM where we will put update image that is coming
- * from PC client. After download, image will be written to flash */
-#define UPD_IMG_RAM_ADDR ((unsigned char *)0x40100000)
-
-/**
- * Begin SPIDUPD get
- */
-extern void
-SpidupdStart (void);
-
-/**********************************************************************/
-
#endif /* __SPIDUPD_HOST_H__ */