Add support for console over UDP (compatible to Ingo Molnar's
authorwdenk <wdenk>
Mon, 2 Aug 2004 21:11:11 +0000 (21:11 +0000)
committerwdenk <wdenk>
Mon, 2 Aug 2004 21:11:11 +0000 (21:11 +0000)
netconsole patch under Linux)

CHANGELOG
common/devices.c
doc/README.NetConsole [new file with mode: 0644]
drivers/Makefile
drivers/netconsole.c [new file with mode: 0644]
include/configs/TQM860L.h
include/devices.h
include/net.h
net/net.c

index 02447d3e9c73c61bd5ba7a1e9bb836a116df5318..4470f8c3dd6acdc994923a12c5963b857bf1e804 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -2,6 +2,9 @@
 Changes since U-Boot 1.1.1:
 ======================================================================
 
+* Add support for console over UDP (compatible to Ingo Molnar's
+  netconsole patch under Linux)
+
 * Patch by Jon Loeliger, 16 Jul 2004:
   - support larger DDR memories up to 2G on the PC8540/8560ADS and
     STXGP3 boards
index b37c99a69b2ff8d666678dee2a160989f2c8e318..bd4dfa024a94460415f5948cc6947215367e54b3 100644 (file)
@@ -201,6 +201,9 @@ int devices_init (void)
 #ifdef CONFIG_USB_TTY
        drv_usbtty_init ();
 #endif
+#ifdef CONFIG_NETCONSOLE
+       drv_nc_init ();
+#endif
 
        return (0);
 }
diff --git a/doc/README.NetConsole b/doc/README.NetConsole
new file mode 100644 (file)
index 0000000..8dc0d29
--- /dev/null
@@ -0,0 +1,68 @@
+
+In U-Boot, we implemented the networked console via the standard
+"devices" mechanism, which means that you can switch between the
+serial and network input/output devices by adjusting the 'stdin' and
+'stdout' environment variables. To switch to the networked console,
+set either of these variables to "nc". Input and output can be
+switched independently.
+
+On the host side, please use this script to access the console:
+
++++++++++++++++++++++++++++++++++++++++++++
+#! /bin/bash
+
+TARGET_IP=$1
+
+stty -icanon -echo intr ^T
+nc -u -l -p 6666 < /dev/null &
+nc -u ${TARGET_IP} 6666
+stty icanon echo intr ^C
++++++++++++++++++++++++++++++++++++++++++++
+
+For Linux, the network-based console needs special configuration.
+Minimally, the host IP address needs to be specified. This can be
+done either via the kernel command line, or by passing parameters
+while loading the netconsole.o module (when used in a loadable module
+configuration). Please refer to Documentation/networking/logging.txt
+file for the original Ingo Molnar's documentation on how to pass
+parameters to the loadable module.
+
+The format of the kernel command line parameter (for the static
+configuration) is as follows:
+
+  netconsole=[src-port]@[src-ip]/[<dev>],[tgt-port]@<tgt-ip>/[tgt-macaddr]
+
+where
+
+  src-port     source for UDP packets
+               (defaults to 6665)
+  src-ip       source IP to use
+               (defaults to the interface's address)
+  dev          network interface
+               (defaults to eth0)
+  tgt-port     port for logging agent
+               (defaults to 6666)
+  tgt-ip       IP address for logging agent
+               (this is the required parameter)
+  tgt-macaddr  ethernet MAC address for logging agent
+               (defaults to broadcast)
+
+Examples:
+
+  netconsole=4444@10.0.0.1/eth1,9353@10.0.0.2/12:34:56:78:9a:bc
+
+or
+
+  netconsole=@/,@192.168.3.1/
+
+Please note that for the Linux networked console to work, the
+ethernet interface has to be up by the time the netconsole driver is
+initialized. This means that in case of static kernel configuration,
+the respective Ethernet interface has to be brought up using the "IP
+Autoconfiguration" kernel feature, which is usually done by defaults
+in the ELDK-NFS-based environment.
+
+To browse the Linux network console output, use the 'netcat' tool invoked
+as follows:
+
+       nc -u -l -p 6666
index afca70e2d0c679edafaffb5e7a7fff7d52e7111e..5f221582a3574edad189610548347e28a2e03198 100644 (file)
@@ -32,7 +32,7 @@ OBJS  = 3c589.o 5701rls.o ali512x.o \
          cs8900.o ct69000.o dataflash.o dc2114x.o dm9000x.o \
          e1000.o eepro100.o \
          i8042.o i82365.o inca-ip_sw.o keyboard.o \
-         lan91c96.o natsemi.o netarm_eth.o \
+         lan91c96.o natsemi.o netarm_eth.o netconsole.o \
          ns16550.o ns8382x.o ns87308.o omap1510_i2c.o \
          pci.o pci_auto.o pci_indirect.o \
          pcnet.o plb2800_eth.o \
diff --git a/drivers/netconsole.c b/drivers/netconsole.c
new file mode 100644 (file)
index 0000000..7e19161
--- /dev/null
@@ -0,0 +1,204 @@
+/*
+ * (C) Copyright 2004
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+
+#ifdef CONFIG_NETCONSOLE
+
+#include <command.h>
+#include <devices.h>
+#include <net.h>
+
+#ifndef CONFIG_NET_MULTI
+#error define CONFIG_NET_MULTI to use netconsole
+#endif
+
+static uchar nc_buf = 0;       /* input buffer */
+static int input_recursion = 0;
+static int output_recursion = 0;
+static int net_timeout;
+
+static void nc_wait_arp_handler (uchar * pkt, unsigned dest, unsigned src,
+                                unsigned len)
+{
+       NetState = NETLOOP_SUCCESS;     /* got arp reply - quit net loop */
+}
+
+static void nc_handler (uchar * pkt, unsigned dest, unsigned src,
+                       unsigned len)
+{
+       if (nc_buf)
+               NetState = NETLOOP_SUCCESS;     /* got input - quit net loop */
+}
+
+static void nc_timeout (void)
+{
+       NetState = NETLOOP_SUCCESS;
+}
+
+void NcStart (void)
+{
+       if (memcmp (NetServerEther, NetEtherNullAddr, 6)) {
+               /* going to check for input packet */
+               NetSetHandler (nc_handler);
+               NetSetTimeout (net_timeout, nc_timeout);
+       } else {
+               /* send arp request */
+               NetSetHandler (nc_wait_arp_handler);
+               NetSendUDPPacket (NetServerEther, NetServerIP, 6665, 6666, 0);
+       }
+}
+
+int nc_input_packet (uchar * pkt, unsigned dest, unsigned src, unsigned len)
+{
+       if (dest != 6666 || !len)
+               return 0;               /* not for us */
+
+       nc_buf = *pkt;
+       return 1;
+}
+
+static void nc_send_packet (const char *buf, int len)
+{
+       DECLARE_GLOBAL_DATA_PTR;
+
+       struct eth_device *eth;
+       int inited = 0;
+       uchar *pkt;
+
+       if (!memcmp (NetServerEther, NetEtherNullAddr, 6))
+               return;
+
+       if ((eth = eth_get_dev ()) == NULL) {
+               return;
+       }
+
+       if (eth->state != ETH_STATE_ACTIVE) {
+               if (eth_init (gd->bd) < 0)
+                       return;
+               inited = 1;
+       }
+       pkt = (uchar *) NetTxPacket + NetEthHdrSize () + IP_HDR_SIZE;
+       memcpy (pkt, buf, len);
+       NetSendUDPPacket (NetServerEther, NetServerIP, 6666, 6665, len);
+
+       if (inited)
+               eth_halt ();
+}
+
+int nc_start (void)
+{
+       if (memcmp (NetServerEther, NetEtherNullAddr, 6))
+               return 0;
+
+       return NetLoop (NETCONS);       /* wait for arp reply */
+}
+
+void nc_putc (char c)
+{
+       if (output_recursion)
+               return;
+       output_recursion = 1;
+
+       nc_send_packet (&c, 1);
+
+       output_recursion = 0;
+}
+
+void nc_puts (const char *s)
+{
+       if (output_recursion)
+               return;
+       output_recursion = 1;
+
+       int len = strlen (s);
+
+       if (len > 512)
+               len = 512;
+
+       nc_send_packet (s, len);
+
+       output_recursion = 0;
+}
+
+int nc_getc (void)
+{
+       input_recursion = 1;
+
+       net_timeout = 0;        /* no timeout */
+       while (!nc_buf)
+               NetLoop (NETCONS);
+
+       input_recursion = 0;
+
+       uchar tmp = nc_buf;
+
+       nc_buf = 0;
+       return tmp;
+}
+
+int nc_tstc (void)
+{
+       struct eth_device *eth;
+
+       if (input_recursion)
+               return 0;
+
+       if (nc_buf)
+               return 1;
+
+       eth = eth_get_dev ();
+       if (eth && eth->state == ETH_STATE_ACTIVE)
+               return 0;       /* inside net loop */
+
+       input_recursion = 1;
+
+       net_timeout = 1;
+       NetLoop (NETCONS);              /* kind of poll */
+
+       input_recursion = 0;
+
+       return nc_buf != 0;
+}
+
+int drv_nc_init (void)
+{
+       device_t dev;
+       int rc;
+
+       memset (&dev, 0, sizeof (dev));
+
+       strcpy (dev.name, "nc");
+       dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM;
+       dev.start = nc_start;
+       dev.putc = nc_putc;
+       dev.puts = nc_puts;
+       dev.getc = nc_getc;
+       dev.tstc = nc_tstc;
+
+       rc = device_register (&dev);
+
+       return (rc == 0) ? 1 : rc;
+}
+
+#endif /* CONFIG_NETCONSOLE */
index adac808e7340fe112e28b585337c671d4cced6c2..bc0f7c7f7570e7fbc9122e4d4c518e2f8e49f531 100644 (file)
@@ -97,6 +97,8 @@
                                CFG_CMD_IDE     | \
                                CFG_CMD_DATE    )
 
+#define CONFIG_NETCONSOLE
+
 /* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
 #include <cmd_confdefs.h>
 
index 09c2c5f511fa093067b4a9f101e7a1704fc1f154..2d9e282e38f16248bc8d3e465e0b3e651eece30d 100644 (file)
@@ -108,5 +108,8 @@ int drv_keyboard_init (void);
 #ifdef CONFIG_USB_TTY
 int    drv_usbtty_init (void);
 #endif
+#ifdef CONFIG_NETCONSOLE
+int    drv_nc_init (void);
+#endif
 
 #endif /* _DEVICES_H_ */
index 68f5fea3e3eeba26e2aa5d11946eb91f6eb679e4..5a6b8083b3ae4bf636251e306b6cfa363a95eb9a 100644 (file)
@@ -314,6 +314,7 @@ extern volatile uchar * NetRxPkt;           /* Current receive packet       */
 extern int             NetRxPktLen;            /* Current rx packet length     */
 extern unsigned                NetIPID;                /* IP ID (counting)             */
 extern uchar           NetBcastAddr[6];        /* Ethernet boardcast address   */
+extern uchar           NetEtherNullAddr[6];
 
 #define VLAN_NONE      4095                    /* untagged                     */
 #define VLAN_IDMASK    0x0fff                  /* mask of valid vlan id        */
@@ -334,7 +335,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 } proto_t;
+typedef enum { BOOTP, RARP, ARP, TFTP, DHCP, PING, DNS, NFS, CDP, NETCONS } proto_t;
 
 /* from net/net.c */
 extern char    BootFile[128];                  /* Boot File name               */
index 6e0288dc0676cc7f2cd427d26b6add770eb58d0c..261f7c187dd95b3ea97a1c9afa21eb2b0965336c 100644 (file)
--- a/net/net.c
+++ b/net/net.c
@@ -148,6 +148,11 @@ static void PingStart(void);
 static void CDPStart(void);
 #endif
 
+#ifdef CONFIG_NETCONSOLE
+void NcStart(void);
+int nc_input_packet(uchar *pkt, unsigned dest, unsigned src, unsigned len);
+#endif
+
 volatile uchar PktBuf[(PKTBUFSRX+1) * PKTSIZE_ALIGN + PKTALIGN];
 
 volatile uchar *NetRxPackets[PKTBUFSRX]; /* Receive packets                    */
@@ -308,6 +313,7 @@ restart:
 #if (CONFIG_COMMANDS & CFG_CMD_PING)
        case PING:
 #endif
+       case NETCONS:
        case TFTP:
                NetCopyIP(&NetOurIP, &bd->bi_ip_addr);
                NetOurGatewayIP = getenv_IPaddr ("gatewayip");
@@ -319,6 +325,7 @@ restart:
 #if (CONFIG_COMMANDS & CFG_CMD_NFS)
                case NFS:
 #endif
+               case NETCONS:
                case TFTP:
                        NetServerIP = getenv_IPaddr ("serverip");
                        break;
@@ -403,6 +410,11 @@ restart:
                case CDP:
                        CDPStart();
                        break;
+#endif
+#ifdef CONFIG_NETCONSOLE
+               case NETCONS:
+                       NcStart();
+                       break;
 #endif
                default:
                        break;
@@ -1259,6 +1271,9 @@ NetReceive(volatile uchar * inpkt, int len)
                                /* save address for later use */
                                memcpy(NetArpWaitPacketMAC, &arp->ar_data[0], 6);
 
+#ifdef CONFIG_NETCONSOLE
+                               (*packetHandler)(0,0,0,0);
+#endif
                                /* modify header, and transmit it */
                                memcpy(((Ethernet_t *)NetArpWaitTxPacket)->et_dest, NetArpWaitPacketMAC, 6);
                                (void) eth_send(NetArpWaitTxPacket, NetArpWaitTxPacketSize);
@@ -1377,6 +1392,12 @@ NetReceive(volatile uchar * inpkt, int len)
                        return;
                }
 
+#ifdef CONFIG_NETCONSOLE
+               nc_input_packet((uchar *)ip +IP_HDR_SIZE,
+                                               ntohs(ip->udp_dst),
+                                               ntohs(ip->udp_src),
+                                               ntohs(ip->udp_len) - 8);
+#endif
                /*
                 *      IP header OK.  Pass the packet to the current handler.
                 */
@@ -1406,6 +1427,7 @@ static int net_check_prereq (proto_t protocol)
 #if (CONFIG_COMMANDS & CFG_CMD_NFS)
        case NFS:
 #endif
+       case NETCONS:
        case TFTP:
                if (NetServerIP == 0) {
                        puts ("*** ERROR: `serverip' not set\n");