[U-Boot] [PATCH 1/3] Add support for Net Boot Controller (NBC) packet

tristan.lelong at blunderer.org tristan.lelong at blunderer.org
Tue Nov 16 19:04:31 CET 2010


From: Tristan Lelong <tristan.lelong at blunderer.org>

This adds the core NBC feature:
 * Integration into u-boot
 * NBC packet processing
 * NetConsole reconfigure

Signed-off-by: Tristan Lelong <tristan.lelong at blunderer.org>
---
 common/main.c |    5 ++
 include/net.h |    6 ++-
 net/Makefile  |    2 +
 net/nbc.c     |  143 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 net/nbc.h     |   39 +++++++++++++++
 net/net.c     |   17 +++++++
 6 files changed, 211 insertions(+), 1 deletions(-)
 create mode 100644 net/nbc.c
 create mode 100644 net/nbc.h

diff --git a/common/main.c b/common/main.c
index d97ccd7..e23b204 100644
--- a/common/main.c
+++ b/common/main.c
@@ -259,6 +259,11 @@ static __inline__ int abortboot(int bootdelay)
 
 	putc('\n');
 
+#ifdef CONFIG_CMD_NBC
+	if (!abort)
+		abort = NBCWait ();
+#endif
+
 #ifdef CONFIG_SILENT_CONSOLE
 	if (abort)
 		gd->flags &= ~GD_FLG_SILENT;
diff --git a/include/net.h b/include/net.h
index a29dafc..25e177f 100644
--- a/include/net.h
+++ b/include/net.h
@@ -359,7 +359,7 @@ extern int		NetState;		/* Network loop state		*/
 extern int		NetRestartWrap;		/* Tried all network devices	*/
 #endif
 
-typedef enum { BOOTP, RARP, ARP, TFTP, DHCP, PING, DNS, NFS, CDP, NETCONS, SNTP } proto_t;
+typedef enum { BOOTP, RARP, ARP, TFTP, DHCP, PING, DNS, NFS, CDP, NETCONS, SNTP, NBC } proto_t;
 
 /* from net/net.c */
 extern char	BootFile[128];			/* Boot File name		*/
@@ -384,6 +384,10 @@ extern IPaddr_t	NetNtpServerIP;			/* the ip address to NTP	*/
 extern int NetTimeOffset;			/* offset time from UTC		*/
 #endif
 
+#if defined(CONFIG_CMD_NBC)
+extern IPaddr_t	NetSrcIP;			/* Packet Src IP addr (0 = unknown)	*/
+#endif
+
 /* Initialize the network adapter */
 extern int	NetLoop(proto_t);
 
diff --git a/net/Makefile b/net/Makefile
index 216d1ec..735e8c6 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -35,6 +35,8 @@ COBJS-$(CONFIG_CMD_NFS)  += nfs.o
 COBJS-$(CONFIG_CMD_RARP) += rarp.o
 COBJS-$(CONFIG_CMD_SNTP) += sntp.o
 COBJS-$(CONFIG_CMD_NET)  += tftp.o
+COBJS-$(CONFIG_CMD_NBC)	 += nbc.o
+
 
 COBJS	:= $(COBJS-y)
 SRCS	:= $(COBJS:.o=.c)
diff --git a/net/nbc.c b/net/nbc.c
new file mode 100644
index 0000000..e1788e4
--- /dev/null
+++ b/net/nbc.c
@@ -0,0 +1,143 @@
+/*
+ * NBC support driver
+ * Network Boot Controller
+ *
+ * Copyright (c) 2010 Tristan Lelong <tristan.lelong at blunderer.org>
+ *
+ */
+
+#include <common.h>
+#include <command.h>
+#include <net.h>
+
+#include "nbc.h"
+
+#ifndef CONFIG_NETCONSOLE
+#error CONFIG_NETCONSOLE should be defined so that nbc can redirect stdin/stdout/stderr
+#endif
+
+static char NBC_Mode_On = 0;
+
+static void NBCHandler (uchar * pkt, unsigned dest, unsigned src, unsigned len)
+{
+	int cnt = 0;
+	char src_ip[16] = "";
+	char *nbcsource = NULL;
+	char ip[16] = "";
+	char mac[18] = "";
+	char hostname[255] = "";
+
+	struct _nbc_packet *nbc_pkt = (struct _nbc_packet *)pkt;
+	nbcsource = getenv ("nbcsource");
+
+	/* check packet validity */
+	if (nbc_pkt->id != 0xD3)
+		goto fail;
+	if (strncmp (nbc_pkt->head, "NBC", 3))
+		goto fail;
+	if (nbc_pkt->size != len)
+		goto fail;
+
+	sprintf (src_ip, "%lu.%lu.%lu.%lu", ((NetSrcIP >> 0) & 0xFF),
+		 ((NetSrcIP >> 8) & 0xFF), ((NetSrcIP >> 16) & 0xFF),
+		 ((NetSrcIP >> 24) & 0xFF));
+
+	if (nbcsource && strcmp (nbcsource, src_ip))
+		goto fail;
+
+	for (cnt = 0; cnt < (nbc_pkt->size - NBC_HEADER_SIZE);) {
+		struct _nbc_chunk *chk =
+		    (struct _nbc_chunk *)(pkt + NBC_HEADER_SIZE + cnt);
+		if (strncmp (chk->name, "IP\0\0", 4) == 0) {
+			if (chk->size != NBC_CHK_IP_SIZE)
+				goto fail;
+			unsigned char *pkt_ip = (unsigned char *)chk->data;
+			sprintf (ip, "%d.%d.%d.%d", pkt_ip[0], pkt_ip[1],
+				 pkt_ip[2], pkt_ip[3]);
+		} else if (strncmp (chk->name, "MAC\0", 4) == 0) {
+			if (chk->size != NBC_CHK_MAC_SIZE)
+				goto fail;
+			unsigned char *pkt_mac = (unsigned char *)chk->data;
+			sprintf (mac, "%02X:%02X:%02X:%02X:%02X:%02X",
+				 pkt_mac[0], pkt_mac[1], pkt_mac[2], pkt_mac[3],
+				 pkt_mac[4], pkt_mac[5]);
+		} else if (strncmp (chk->name, "HOST", 4) == 0) {
+			unsigned char *pkt_hostname =
+			    (unsigned char *)chk->data;
+			if (chk->size >= NBC_CHK_HOSTNAME_SIZE)
+				goto fail;
+			strncpy (hostname, pkt_hostname, chk->size);
+			hostname[chk->size] = '\0';
+		}
+		cnt += NBC_CHK_HEADER_SIZE + chk->size;
+	}
+
+	/* test if we are targeted by the magic packet */
+	if (strlen (mac)) {
+		char *our_mac = getenv ("ethaddr");
+		debug ("mac filter: cmp(%s,%s)\n", our_mac, mac);
+		if (strcmp (mac, our_mac))
+			goto fail;
+	}
+
+	if (strlen (hostname)) {
+		char *our_hostname = getenv ("hostname");
+		debug ("hostname filter: cmp(%s,%s)\n", our_hostname, hostname);
+		if (strcmp (hostname, our_hostname))
+			goto fail;
+	}
+
+	/* set server ip */
+	setenv ("serverip", src_ip);
+
+	/* set gateway ip */
+	setenv ("gatewayip", src_ip);
+
+	/* set addrip */
+	setenv ("ipaddr", ip);
+
+	printf ("activated nc from [%s] to [%s]\n", ip, src_ip);
+
+	/* activate the netconsole */
+	setenv ("ncip", src_ip);
+	setenv ("stdin", "nc");
+	setenv ("stdout", "nc");
+	setenv ("stderr", "nc");
+	console_assign (stdin, "nc");
+	console_assign (stdout, "nc");
+	console_assign (stderr, "nc");
+
+	NBC_Mode_On = 1;
+
+	NetState = NETLOOP_SUCCESS;
+
+	return;
+fail:
+	debug ("not a valid nbc magic packet\n");
+}
+
+static void NBCTimeout (void)
+{
+	NetState = NETLOOP_FAIL;
+	debug ("NBC Timeout!\n");
+}
+
+int NBCWait (void)
+{
+	char *nbcinhibit = getenv ("nbcinhibit");
+	if (nbcinhibit)
+		return 0;
+
+	NetLoop (NBC);
+
+	if (NBC_Mode_On) {
+		return 1;
+	}
+	return 0;
+}
+
+void NBCStart (void)
+{
+	NetSetTimeout (1000, NBCTimeout);
+	NetSetHandler (NBCHandler);
+}
diff --git a/net/nbc.h b/net/nbc.h
new file mode 100644
index 0000000..40371a5
--- /dev/null
+++ b/net/nbc.h
@@ -0,0 +1,39 @@
+/*
+ * (C) Tristan Lelong <tristan.lelong at blunderer.org> 2010
+ *  Copyright 2010, Tristan Lelong <tristan.lelong at blunderer.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2, or (at
+ * your option) any later version.
+ */
+
+#ifndef __NBC_H__
+#define __NBC_H__
+
+#define NBC_SERVICE_PORT 	4446
+#define NBC_TIMEOUT      	2000
+
+#define NBC_CHK_HEADER_SIZE	5
+#define NBC_HEADER_SIZE		5
+#define NBC_CHK_IP_SIZE		4
+#define NBC_CHK_MAC_SIZE	6
+#define NBC_CHK_HOSTNAME_SIZE	255
+
+struct _nbc_packet {
+	unsigned char id;
+	unsigned char head[3];
+	unsigned char size;
+	unsigned char data[255];
+};
+
+struct _nbc_chunk {
+	unsigned char name[4];
+	unsigned char size;
+	unsigned char data[255];
+};
+
+extern void NBCStart (void);
+extern int NBCWait (void);
+
+#endif
diff --git a/net/net.c b/net/net.c
index d5a5429..b722048 100644
--- a/net/net.c
+++ b/net/net.c
@@ -97,6 +97,9 @@
 #if defined(CONFIG_CMD_DNS)
 #include "dns.h"
 #endif
+#if defined(CONFIG_CMD_NBC)
+#include "nbc.h"
+#endif
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -180,6 +183,10 @@ IPaddr_t	NetNtpServerIP;		/* NTP server IP address		*/
 int		NetTimeOffset=0;	/* offset time from UTC			*/
 #endif
 
+#if defined(CONFIG_CMD_NBC)
+IPaddr_t	NetSrcIP;		/* Src IP addr (0 = unknown)		*/
+#endif
+
 #ifdef CONFIG_NETCONSOLE
 void NcStart(void);
 int nc_input_packet(uchar *pkt, unsigned dest, unsigned src, unsigned len);
@@ -384,6 +391,11 @@ restart:
 		NetDevExists = 1;
 #endif
 		switch (protocol) {
+#if defined(CONFIG_CMD_NBC)
+		case NBC:
+			NBCStart ();
+			break;
+#endif
 		case TFTP:
 			/* always use ARP to get server ethernet address */
 			TftpStart();
@@ -1631,6 +1643,7 @@ NetReceive(volatile uchar * inpkt, int len)
 			ushort *sumptr;
 			ushort  sumlen;
 
+
 			xsum  = ip->ip_p;
 			xsum += (ntohs(ip->udp_len));
 			xsum += (ntohl(ip->ip_src) >> 16) & 0x0000ffff;
@@ -1673,6 +1686,10 @@ NetReceive(volatile uchar * inpkt, int len)
 						ntohs(ip->udp_src),
 						ntohs(ip->udp_len) - 8);
 #endif
+
+#ifdef CONFIG_CMD_NBC
+		NetSrcIP = NetReadIP ((void *)&ip->ip_src);
+#endif
 		/*
 		 *	IP header OK.  Pass the packet to the current handler.
 		 */
-- 
1.7.2.3



More information about the U-Boot mailing list