From: Tristan Lelong <tristan.lel...@blunderer.org>

This tool send NBC packet filled with data provided on command line
It can be used in combination with netconsole by calling:
BOARD_IP=192.168.0.2 ./sendnbc -i $BOARD_IP && ./netconsole $BOARD_IP

Signed-off-by: Tristan Lelong <tristan.lel...@blunderer.org>
---
 tools/Makefile  |    6 ++
 tools/sendnbc.c |  219 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 225 insertions(+), 0 deletions(-)
 create mode 100644 tools/sendnbc.c

diff --git a/tools/Makefile b/tools/Makefile
index 619c9f2..e1719fc 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -45,6 +45,7 @@ CONFIG_CMD_LOADS = y
 CONFIG_CMD_NET = y
 CONFIG_INCA_IP = y
 CONFIG_NETCONSOLE = y
+CONFIG_CMD_NBC = y
 CONFIG_SHA1_CHECK_UB_IMG = y
 endif
 
@@ -64,6 +65,7 @@ BIN_FILES-$(CONFIG_CMD_LOADS) += img2srec$(SFX)
 BIN_FILES-$(CONFIG_INCA_IP) += inca-swap-bytes$(SFX)
 BIN_FILES-y += mkimage$(SFX)
 BIN_FILES-$(CONFIG_NETCONSOLE) += ncb$(SFX)
+BIN_FILES-$(CONFIG_CMD_NBC) += sendnbc$(SFX)
 BIN_FILES-$(CONFIG_SHA1_CHECK_UB_IMG) += ubsha1$(SFX)
 
 # Source files which exist outside the tools directory
@@ -86,6 +88,7 @@ NOPED_OBJ_FILES-y += kwbimage.o
 NOPED_OBJ_FILES-y += imximage.o
 NOPED_OBJ_FILES-y += mkimage.o
 OBJ_FILES-$(CONFIG_NETCONSOLE) += ncb.o
+OBJ_FILES-$(CONFIG_CMD_NBC) += sendnbc.o
 NOPED_OBJ_FILES-y += os_support.o
 OBJ_FILES-$(CONFIG_SHA1_CHECK_UB_IMG) += ubsha1.o
 
@@ -197,6 +200,9 @@ $(obj)ncb$(SFX):    $(obj)ncb.o
        $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^
        $(HOSTSTRIP) $@
 
+$(obj)sendnbc$(SFX):   $(obj)sendnbc.o
+       $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^
+
 $(obj)ubsha1$(SFX):    $(obj)os_support.o $(obj)sha1.o $(obj)ubsha1.o
        $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^
 
diff --git a/tools/sendnbc.c b/tools/sendnbc.c
new file mode 100644
index 0000000..03bf5af
--- /dev/null
+++ b/tools/sendnbc.c
@@ -0,0 +1,219 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netinet/ether.h>
+
+static void usage (char *argv0)
+{
+       printf
+           ("SENDNBC: sends a magic packet to u-boot board to interrupt the 
autoboot\n");
+       printf ("         and reconfigure u-boot in netconsole mode.\n");
+       printf
+           ("         Use in combination with netconsole to connect and 
control\n");
+       printf ("        your u-boot device\n");
+       printf
+           ("   Ex: BOARD_IP=192.168.0.2 ./sendnbc -i $BOARD_IP -d eth0 && 
./netconsole $BOARD_IP\n");
+       printf ("\nusage: %s [options]\n", argv0);
+       printf (" -i <ip addr>: the ip addr to assign to u-boot board\n");
+       printf (" -m <mac addr>: the targeted board mac addr \n");
+       printf (" -n <hostname>: the targeted board hostname \n");
+       printf
+           (" -d <device>: the net interface to use for broadcasting (ex: 
eth0). Must be root to use this option\n");
+       printf (" -h: display this help\n");
+}
+
+static int build_nbc_pkt (char *buf, int buf_len, char *ip, char *mac,
+                         char *hostname)
+{
+       int offset = 0;
+       char *size = NULL;
+       char *ip_size = NULL;
+       char *mac_size = NULL;
+       char *hostname_size = NULL;
+
+       struct in_addr binip;
+       struct ether_addr binmac;
+
+       memset (buf, 0, buf_len);
+
+       buf[0] = (char)0xD3;    /* magic number */
+       offset += 1;
+
+       strcpy (buf + offset, "NBC");   /* packet header */
+       offset += 3;
+
+       size = (char *)(buf + offset);  /* msg total size */
+       offset += 1;
+
+       strcpy (buf + offset, "IP");    /* IP chunk header */
+       offset += 4;
+
+       ip_size = (char *)(buf + offset);       /* IP chunk size */
+       offset += 1;
+
+       inet_pton (AF_INET, ip, &binip);
+       memcpy (buf + offset, &binip, sizeof (struct in_addr)); /* IP chunk 
data */
+       offset += sizeof (struct in_addr);
+       *ip_size = sizeof (struct in_addr);
+
+       if (mac) {
+               strcpy (buf + offset, "MAC");   /* MAC chunk header */
+               offset += 4;
+
+               mac_size = (char *)(buf + offset);      /* MAC chunk size */
+               offset += 1;
+
+               ether_aton_r (mac, &binmac);
+               memcpy (buf + offset, &binmac, sizeof (struct ether_addr));     
/* MAC chunk data */
+               offset += sizeof (struct ether_addr);
+               *mac_size = sizeof (struct ether_addr);
+       }
+
+       if (hostname) {
+               strcpy (buf + offset, "HOST");  /* HOST chunk header */
+               offset += 4;
+
+               hostname_size = (char *)(buf + offset); /* HOST chunk size */
+               offset += 1;
+
+               strcpy (buf + offset, hostname);        /* HOST chunk data */
+               offset += strlen (hostname);
+               *hostname_size = strlen (hostname);
+       }
+
+       *size = offset;
+
+       return offset;
+}
+
+int main (int argc, char *argv[])
+{
+       char buf[255];
+       int s, len, o, nbcport = 4446, netconsoleport = 6666;
+       int buf_len = sizeof (buf);
+       char option;
+       char *ip = NULL;
+       char *mac = NULL;
+       char *device = NULL;
+       char *hostname = NULL;
+       struct sockaddr_in addr;
+       struct sockaddr_in broadcast_addr;
+       socklen_t addr_len = sizeof (addr);
+       socklen_t broadcast_addr_len = sizeof (broadcast_addr);
+
+       s = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+       if (s < 0) {
+               perror ("Error with socket creation");
+               return 1;
+       }
+       while ((option = getopt (argc, argv, "hn:m:i:d:")) >= 0) {
+               switch (option) {
+               case 'h':
+                       usage (argv[0]);
+                       exit (0);
+               case 'd':
+                       device = optarg;
+                       break;
+               case 'n':
+                       hostname = optarg;
+                       break;
+               case 'm':
+                       mac = optarg;
+                       break;
+               case 'i':
+                       ip = optarg;
+                       break;
+               default:
+                       usage (argv[0]);
+                       exit (0);
+               }
+       }
+
+       if (!ip) {
+               usage (argv[0]);
+               exit (0);
+       }
+
+       /* set sockoptions */
+       o = 1;
+       len = 4;
+       setsockopt (3, SOL_SOCKET, SO_REUSEADDR, &o, len);
+       o = 1;
+       len = 4;
+       setsockopt (3, SOL_SOCKET, SO_BROADCAST, &o, len);
+       if (device) {
+               len = strlen (device);
+               setsockopt (3, SOL_SOCKET, SO_BINDTODEVICE, device, len);
+       }
+
+       /* configure socket */
+       memset (&addr, 0, sizeof (struct sockaddr_in));
+       addr.sin_family = AF_INET;
+       addr.sin_port = htons (netconsoleport);
+       addr.sin_addr.s_addr = INADDR_ANY;
+
+       memset (&broadcast_addr, 0, sizeof (struct sockaddr_in));
+       broadcast_addr.sin_family = AF_INET;
+       broadcast_addr.sin_port = htons (nbcport);
+       broadcast_addr.sin_addr.s_addr = INADDR_BROADCAST;
+
+       if (bind (s, (struct sockaddr *)&addr, sizeof (addr)) < 0) {
+               perror ("error with bind");
+               close (s);
+       }
+
+       /* build packets */
+       buf_len = build_nbc_pkt (buf, sizeof (buf), ip, mac, hostname);
+
+       for (;;) {
+               char recv_buf = '\n';
+               struct in_addr binip;
+               struct sockaddr_in board_addr;
+               socklen_t board_addr_len = sizeof (struct sockaddr_in);
+
+               memset (&addr, 0, sizeof (struct sockaddr_in));
+               inet_pton (AF_INET, ip, &binip);
+               board_addr.sin_family = AF_INET;
+               board_addr.sin_port = htons (netconsoleport);
+               memcpy (&board_addr.sin_addr.s_addr, &binip,
+                       sizeof (struct in_addr));
+
+               /* send the magic packet */
+               len =
+                   sendto (s, buf, buf_len, 0,
+                           (struct sockaddr *)&broadcast_addr,
+                           broadcast_addr_len);
+               if (len < 0) {
+                       perror ("error in send");
+                       break;
+               }
+
+               usleep (100000);
+
+               /* check for u-boot in netconsole mode */
+               len =
+                   sendto (s, &recv_buf, 1, 0, (struct sockaddr *)&board_addr,
+                           board_addr_len);
+               len = recv (s, &recv_buf, 1, MSG_PEEK | MSG_DONTWAIT);
+               if (len < 0) {
+                       if (errno != EAGAIN) {
+                               perror ("error in recv");
+                               break;
+                       }
+               } else if (len > 0) {
+                       break;
+               }
+       }
+       if (len < 0) {
+               return 1;
+       }
+
+       close (s);
+
+       return 0;
+}
-- 
1.7.2.3

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to