summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSuriyan Ramasami <suriyan.r@gmail.com>2014-03-06 17:53:04 +0400
committerMauro Ribeiro <mauro.ribeiro@hardkernel.com>2014-03-06 17:53:04 +0400
commit5d39bef9758b4cd6e39046f78b75aaee91271a48 (patch)
tree60ed0eb8cabdaea3ddb44176d0b02934f876d28e
parenta1ce4b9c109d9629c4ce68fabbf6b0dbf2549f2e (diff)
downloadu-boot-5d39bef9758b4cd6e39046f78b75aaee91271a48.tar.xz
Enable OTG port as CDC ETH for console output using netconsole.
1. Added DHCPSERVER functionality in u-boot to auto configure network. 2. Enabled CDC ETH OTG 3. Added automatic CDC ETH console if OTG cable connected on boot. 4. Added script tools/nc.odroid for automatic netconsole. The Odroid is configured with IP 10.10.10.11 and the other end is DHCP served an address of 10.10.10.10. Signed-off-by: Suriyan Ramasami <suriyan.r@gmail.com> The steps to get console over the OTG port is as follows: 1. Power off Odroid 2. Connect OTG port with cable to USB host 3. In host ensure firewall is not blocking port 6666 and DHCP ports 67 and 68. All are UDP. 4. In host ensure automatic configuration of ethernet interface is turned on in Network Manager. Its usually enabled by default. On the host it will appear as interface usb0 5. Run tools/nc.odroid 6. Power on Odroid board.
-rw-r--r--board/samsung/smdk4212/config.mk2
-rw-r--r--board/samsung/smdk4212/smdk4212.c7
-rw-r--r--common/cmd_bootscan.c86
-rw-r--r--common/main.c7
-rw-r--r--drivers/net/netconsole.c23
-rw-r--r--drivers/usb/gadget/Makefile2
-rw-r--r--drivers/usb/gadget/ether.c81
-rw-r--r--drivers/usb/gadget/gadget_chips.h8
-rw-r--r--drivers/usb/gadget/s3c_udc_otg.c9
-rw-r--r--include/configs/smdk4412.h18
-rw-r--r--include/linux/netdevice.h62
-rw-r--r--include/net.h7
-rw-r--r--net/bootp.c235
-rw-r--r--net/bootp.h4
-rw-r--r--net/net.c9
-rw-r--r--tools/nc.odroid31
16 files changed, 543 insertions, 48 deletions
diff --git a/board/samsung/smdk4212/config.mk b/board/samsung/smdk4212/config.mk
index dd7ec078ec..822a6e4943 100644
--- a/board/samsung/smdk4212/config.mk
+++ b/board/samsung/smdk4212/config.mk
@@ -10,4 +10,4 @@
#
#
-CONFIG_SYS_TEXT_BASE = 0xc3e00000
+CONFIG_SYS_TEXT_BASE = 0x43e00000
diff --git a/board/samsung/smdk4212/smdk4212.c b/board/samsung/smdk4212/smdk4212.c
index 0c6de49c05..990fb56053 100644
--- a/board/samsung/smdk4212/smdk4212.c
+++ b/board/samsung/smdk4212/smdk4212.c
@@ -267,6 +267,13 @@ int board_eth_init(bd_t *bis)
#ifdef CONFIG_SMC911X
rc = smc911x_initialize(0, CONFIG_SMC911X_BASE);
#endif
+
+#ifdef CONFIG_USB_ETHER
+ setenv("stdin", "serial");
+ setenv("stdout", "serial");
+ setenv("stderr", "serial");
+ rc = usb_eth_initialize(bis);
+#endif
return rc;
}
diff --git a/common/cmd_bootscan.c b/common/cmd_bootscan.c
index 1183fb1642..1642ad4a3d 100644
--- a/common/cmd_bootscan.c
+++ b/common/cmd_bootscan.c
@@ -701,7 +701,9 @@ static int bootscan_menu(struct bootscan_bootables bootlist[], int bootdelay)
display_banner();
puts(BOOTSCAN_OPTIONS_DIVIDER "\n");
- m = menu_create(BOOTSCAN_OPTIONS_HEADER, 60, 1, bootscan_menuprint,
+ /* 15000 is roughly 1 second when using get_ticks() */
+ /* so for a 5 second wait time its 75000 */
+ m = menu_create(BOOTSCAN_OPTIONS_HEADER, 75000, 1, bootscan_menuprint,
NULL, NULL);
/*
@@ -1187,13 +1189,52 @@ static void gen_set_ncip(char ncip[20])
}
}
-static void bootscan_netconsole()
+/* Return 1 if netconsole is set on the OTG port */
+static int bootscan_otg_netconsole() {
+ char *ip;
+ int issues = 0;
+
+ /*
+ * Its true we are using this form of netconsole if the following
+ * is true:
+ * 1. usb_cable_connected() is true.
+ * 2. Check if ipaddr is CONFIG_USBNET_DEV_IP and ncip is
+ * CONFIG_USBNET_HOST_IP
+ */
+ if (!usb_cable_connected()) {
+ printf("Cable not connected or failed to initialize.\n");
+ issues++;
+ }
+ ip = getenv("ipaddr");
+ if (ip && strcmp(ip, CONFIG_USBNET_DEV_IP)) {
+ printf("ipaddr %s is not %s\n", ip, CONFIG_USBNET_DEV_IP);
+ issues++;
+ }
+ ip = getenv("ncip");
+ if (ip && strcmp(ip, CONFIG_USBNET_HOST_IP)) {
+ printf("ncip %s is not %s\n", ip, CONFIG_USBNET_HOST_IP);
+ issues++;
+ }
+ if (issues)
+ return 0;
+ else
+ return 1;
+}
+
+/* Return 1 if netconsole is being used for in/out/err */
+static int bootscan_netconsole()
{
char *tmp, ncip[20];
/* Lets initialize stuff for netconsole */
- if (!is_eth_dev_on_usb_host())
- return
+
+ /* Lets first check the OTG netconsole */
+ if (bootscan_otg_netconsole())
+ return 1;
+
+ if (!is_eth_dev_on_usb_host()) {
+ return 0;
+ }
/* Issue a dhcp first */
setenv("abcdtest", "no");
@@ -1203,7 +1244,7 @@ static void bootscan_netconsole()
/* Check if ipaddr is set - either thru dhcp or static */
tmp = getenv("ipaddr");
if (tmp == NULL)
- return;
+ return 0;
tmp = getenv("ncip");
if (tmp == NULL) {
@@ -1213,9 +1254,21 @@ static void bootscan_netconsole()
gen_set_ncip(ncip);
}
- setenv("nc_test", "ping ${ncip}");
- setenv("nc_start", "setenv stdin serial,nc; setenv stdout serial,nc; setenv stderr serial,nc; version");
- run_command("run nc_test nc_start", 0);
+ tmp = getenv("ncip");
+ NetPingIP = string_to_ip(tmp);
+ if (NetLoop(PING) < 0)
+ return 0;
+
+ /* Destination IP ncip pings! */
+ setenv("stdin", "serial,nc");
+ setenv("stdout", "serial,nc");
+ setenv("stderr", "serial,nc");
+ printf("Welcome to netconsole over USB Ethernet\n");
+
+ extern char version_string[];
+ printf("\n%s\n", version_string);
+
+ return 1;
}
/* bootlist[] can hold a max of BOOTSCAN_MAX_BOOTABLES entries */
@@ -1230,18 +1283,13 @@ static void populate_bootlist(struct bootscan_bootables bootlist[])
bootindex = 0;
i = 0;
- /* Lets initialize the usb subsystem */
- run_command("usb start", 0);
-
-#if defined(CONFIG_USB_KEYBOARD)
-# if defined(CONFIG_CONSOLE_MUX)
- run_command("setenv stdin serial,usbkbd", 0);
-# else
- run_command("setenv stdin usbkbd", 0);
-# endif
-#endif
+ if (!bootscan_netconsole()) {
+ /* If it returns 0 netconsole is not set */
+ setenv("stdin", "serial,usbkbd");
+ }
- bootscan_netconsole();
+ /* Lets initialize the usb HOST system subsystem */
+ //run_command("usb start", 0);
/* This scans the partitions in the IDE storage */
#if defined(CONFIG_CMD_IDE)
diff --git a/common/main.c b/common/main.c
index ae37fee46d..a5860136bd 100644
--- a/common/main.c
+++ b/common/main.c
@@ -349,9 +349,6 @@ static void process_boot_delay(void)
debug ("### main_loop entered: bootdelay=%d\n\n", bootdelay);
-#if defined(CONFIG_MENU_SHOW)
- bootdelay = menu_show(bootdelay);
-#endif
# ifdef CONFIG_BOOT_RETRY_TIME
init_cmd_timeout ();
# endif /* CONFIG_BOOT_RETRY_TIME */
@@ -396,7 +393,11 @@ static void process_boot_delay(void)
int prev = disable_ctrlc(1); /* disable Control C checking */
#endif
+#if defined(CONFIG_MENU_SHOW)
+ bootdelay = menu_show(bootdelay);
+#else
run_command_list(s, -1, 0);
+#endif
#ifdef CONFIG_AUTOBOOT_KEYED
disable_ctrlc(prev); /* restore Control C checking */
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index 86a567cdaa..3d0d45d62e 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -16,6 +16,8 @@ DECLARE_GLOBAL_DATA_PTR;
#define CONFIG_NETCONSOLE_BUFFER_SIZE 512
#endif
+extern unsigned dhcpserver;
+
static char input_buffer[CONFIG_NETCONSOLE_BUFFER_SIZE];
static int input_size; /* char count in input buffer */
static int input_offset; /* offset to valid chars in input buffer */
@@ -103,9 +105,16 @@ static int refresh_settings_from_env(void)
if (is_broadcast(nc_ip))
/* broadcast MAC address */
memset(nc_ether, 0xff, sizeof(nc_ether));
- else
- /* force arp request */
- memset(nc_ether, 0, sizeof(nc_ether));
+ else {
+ debug("%s dhcpserver: %d\n", __func__, dhcpserver);
+ if (dhcpserver) {
+ eth_parse_enetaddr(nc_ether, CONFIG_USBNET_HOST_ADDR);
+ }
+ else {
+ /* force arp request */
+ memset(nc_ether, 0, sizeof(nc_ether));
+ }
+ }
}
return 0;
}
@@ -333,6 +342,14 @@ int drv_nc_init(void)
/* Deregister nc - helpful when its thru USB */
int usb_nc_deregister(void)
{
+#ifdef CONFIG_USB_ETHER
+ struct eth_device *ethd;
+
+ ethd = eth_get_dev();
+ debug("Calling usb_eth_halt\n");
+ usb_eth_halt(ethd);
+#endif
+
#ifdef CONFIG_SYS_STDIO_DEREGISTER
return stdio_deregister("nc");
#else
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index a91b32a645..adc069ffb0 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -9,7 +9,7 @@ include $(TOPDIR)/config.mk
LIB := $(obj)libusb_gadget.o
COBJS-$(CONFIG_USB_GADGET) += epautoconf.o config.o usbstring.o
-COBJS-$(CONFIG_USB_ETHER) += epautoconf.o config.o usbstring.o
+#COBJS-$(CONFIG_USB_ETHER) += epautoconf.o config.o usbstring.o
COBJS-$(CONFIG_S3C_USBD) += usbd-otg-hs.o
# new USB gadget layer dependencies
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index cc6cc1f32a..752ca036f7 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -30,6 +30,7 @@ extern struct platform_data brd;
unsigned packet_received, packet_sent;
+unsigned dhcpserver;
#define GFP_ATOMIC ((gfp_t) 0)
#define GFP_KERNEL ((gfp_t) 0)
@@ -1110,7 +1111,7 @@ static int eth_set_config(struct eth_dev *dev, unsigned number,
}
dev->config = number;
- printf("%s speed config #%d: %d mA, %s, using %s\n",
+ debug("%s speed config #%d: %d mA, %s, using %s\n",
speed, number, power, driver_desc,
rndis_active(dev)
? "RNDIS"
@@ -1163,7 +1164,7 @@ static void eth_status_complete(struct usb_ep *ep, struct usb_request *req)
if (event->bNotificationType ==
USB_CDC_NOTIFY_SPEED_CHANGE) {
l_ethdev.network_started = 1;
- printf("USB network up!\n");
+ debug("USB network up!\n");
}
}
req->context = NULL;
@@ -2277,18 +2278,18 @@ autoconf_fail:
* - tx queueing enabled if open *and* carrier is "on"
*/
- printf("using %s, OUT %s IN %s%s%s\n", gadget->name,
+ debug("using %s, OUT %s IN %s%s%s\n", gadget->name,
out_ep->name, in_ep->name,
status_ep ? " STATUS " : "",
status_ep ? status_ep->name : ""
);
- printf("MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
+ debug("MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
dev->net->enetaddr[0], dev->net->enetaddr[1],
dev->net->enetaddr[2], dev->net->enetaddr[3],
dev->net->enetaddr[4], dev->net->enetaddr[5]);
if (cdc || rndis)
- printf("HOST MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
+ debug("HOST MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
dev->host_mac[0], dev->host_mac[1],
dev->host_mac[2], dev->host_mac[3],
dev->host_mac[4], dev->host_mac[5]);
@@ -2336,6 +2337,11 @@ static int usb_eth_init(struct eth_device *netdev, bd_t *bd)
struct usb_gadget *gadget;
unsigned long ts;
unsigned long timeout = USB_CONNECT_TIMEOUT;
+ char *tmpstr;
+ char saveipaddr[20], savenetmask[20];
+
+ saveipaddr[0] = '\0';
+ savenetmask[0] = '\0';
if (!netdev) {
error("received NULL ptr");
@@ -2370,6 +2376,9 @@ static int usb_eth_init(struct eth_device *netdev, bd_t *bd)
if (usb_gadget_register_driver(&eth_driver) < 0)
goto fail;
+ if (!usb_cable_connected())
+ goto fail;
+
dev->network_started = 0;
packet_received = 0;
@@ -2377,10 +2386,8 @@ static int usb_eth_init(struct eth_device *netdev, bd_t *bd)
gadget = dev->gadget;
usb_gadget_connect(gadget);
-
- if (getenv("cdc_connect_timeout"))
- timeout = simple_strtoul(getenv("cdc_connect_timeout"),
- NULL, 10) * CONFIG_SYS_HZ;
+#define CDC_CONNECT_TIMEOUT 100
+ timeout = CDC_CONNECT_TIMEOUT * CONFIG_SYS_HZ;
ts = get_timer(0);
while (!l_ethdev.network_started) {
/* Handle control-c and timeouts */
@@ -2393,8 +2400,64 @@ static int usb_eth_init(struct eth_device *netdev, bd_t *bd)
packet_received = 0;
rx_submit(dev, dev->rx_req, 0);
+
+ dhcpserver = 1;
+/*
+ * We are here implies cable is connected, CDC ETH OTG initialized
+ * We now can bravely set ipaddr to CONFIG_USBNET_DEV_IP
+ * For now lets not set ncip to CONFIG_USBNET_HOST_IP
+ * We call DHCPServer() and relinquish control.
+ * This function and other supporting functions are in net/bootp.c
+ * DHCPServer() shall return 0 if all is OK.
+ * It returns -1 on failure.
+*/
+
+ /* Save the original ipaddr and netmask values */
+ tmpstr = getenv("ipaddr");
+ if (tmpstr)
+ strncpy(saveipaddr, tmpstr, sizeof(saveipaddr));
+ tmpstr = getenv("netmask");
+ if (tmpstr)
+ strncpy(savenetmask, tmpstr, sizeof(savenetmask));
+ setenv("ipaddr", CONFIG_USBNET_DEV_IP);
+ setenv("netmask", CONFIG_USBNET_DEV_NETMASK);
+
+ if (DhcpServer() < 0) {
+ /* No DHCP packet found */
+ /* Note that on a timeout dhcpserver is set to 3 */
+ debug("No DHCP packet received.\n");
+ goto fail;
+ }
+ else {
+ /* Note dhcpserver is set to 2 in NetLoop() */
+ debug("DHCP server success.\n");
+ setenv("ncip", CONFIG_USBNET_HOST_IP);
+ setenv("stdout", "serial,nc");
+ setenv("stderr", "serial,nc");
+ tstc();
+ }
+
+ /* we are here - cable connected, DHCP set. Lets give the user */
+ /* some kind of output */
+ int netconsole_ready_timeout = 10;
+ puts("\n\nWelcome to Netconsole over CDC ETH OTG.\n");
+ printf("After the countdown press Enter to get to U-Boot prompt\n");
+ printf("For BootMenu choice wait for the boot menu to show up\n\n");
+ while (netconsole_ready_timeout) {
+ printf("\rNetconsole over CDC ETH OTG - (%.2d s)",
+ netconsole_ready_timeout);
+ mdelay(1000);
+ netconsole_ready_timeout--;
+ }
+ puts("\n");
+
return 0;
fail:
+ /* We fail, lets correct stdout and remove nc */
+ setenv("stdin", "serial");
+ setenv("ipaddr", saveipaddr);
+ setenv("netmask", savenetmask);
+
return -1;
}
diff --git a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h
index aa54b8547e..ffaa6a3f05 100644
--- a/drivers/usb/gadget/gadget_chips.h
+++ b/drivers/usb/gadget/gadget_chips.h
@@ -97,6 +97,12 @@
#define gadget_is_s3c2410(g) 0
#endif
+#ifdef CONFIG_USB_GADGET_S3C_UDC_OTG
+#define gadget_is_s3c_udc_otg(g) (!strcmp("s3c-udc", (g)->name))
+#else
+#define gadget_is_s3c_udc_otg(g) 0
+#endif
+
#ifdef CONFIG_USB_GADGET_AT91
#define gadget_is_at91(g) (!strcmp("at91_udc", (g)->name))
#else
@@ -223,5 +229,7 @@ static inline int usb_gadget_controller_number(struct usb_gadget *gadget)
return 0x21;
else if (gadget_is_fotg210(gadget))
return 0x22;
+ else if (gadget_is_s3c_udc_otg(gadget))
+ return 0x23;
return -ENOENT;
}
diff --git a/drivers/usb/gadget/s3c_udc_otg.c b/drivers/usb/gadget/s3c_udc_otg.c
index b58a5965aa..cc290f7ab7 100644
--- a/drivers/usb/gadget/s3c_udc_otg.c
+++ b/drivers/usb/gadget/s3c_udc_otg.c
@@ -155,7 +155,7 @@ void otg_phy_init(struct s3c_udc *dev)
dev->pdata->phy_control(1);
/*USB PHY0 Enable */
- printf("USB PHY0 Enable\n");
+ debug("USB PHY0 Enable\n");
/* Enable PHY */
writel(readl(usb_phy_ctrl) | USB_PHY_CTRL_EN0, usb_phy_ctrl);
@@ -294,6 +294,13 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
&& driver->speed != USB_SPEED_HIGH)
|| !driver->bind || !driver->disconnect || !driver->setup)
return -EINVAL;
+ if (!dev) {
+ extern s5pc210_otg_data;
+
+ s3c_udc_probe(&s5pc210_otg_data);
+ dev = the_controller;
+ }
+
if (!dev)
return -ENODEV;
if (dev->driver)
diff --git a/include/configs/smdk4412.h b/include/configs/smdk4412.h
index ec0c2cc482..54a86eea4a 100644
--- a/include/configs/smdk4412.h
+++ b/include/configs/smdk4412.h
@@ -214,12 +214,27 @@
/* NETCONSOLE */
#define CONFIG_NETCONSOLE
#define CONFIG_CMD_DHCP
-#define CONFIG_CMD_MULTI
+#define CONFIG_NET_MULTI
+
+/* USB OTG Ethernet */
+#define CONFIG_USB_ETHER
+#define CONFIG_USB_ETH_CDC
+
+/* USB OTG MAC Addresses for HOST and DEVICE */
+#define CONFIG_USBNET_DEV_ADDR "DE:AD:BE:EF:00:02"
+#define CONFIG_USBNET_DEV_IP "10.10.10.11"
+#define CONFIG_USBNET_DEV_NETMASK "255.255.255.0"
+
+#define CONFIG_USBNET_HOST_ADDR "DE:AD:BE:EF:00:01"
+#define CONFIG_USBNET_HOST_IP "10.10.10.10"
+#define CONFIG_USBNET_HOST_NETMASK "255.255.255.0"
/* CONSOLE MUX */
#define CONFIG_CONSOLE_MUX
#define CONFIG_SYS_CONSOLE_IS_IN_ENV
+#define CONFIG_PREBOOT "setenv stdin serial,nc"
+
#define CONFIG_CMD_BOOTM
/***********************************************************
@@ -257,6 +272,7 @@
#define CONFIG_CMD_BOOTSCAN
#define CONFIG_MENU
#define CONFIG_MENU_SHOW
+
#ifdef CONFIG_MENU_SHOW
#define CONFIG_BOOTP_MAY_FAIL
#endif
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
new file mode 100644
index 0000000000..12e8cc19be
--- /dev/null
+++ b/include/linux/netdevice.h
@@ -0,0 +1,62 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Definitions for the Interfaces handler.
+ *
+ * Version: @(#)dev.h 1.0.10 08/12/93
+ *
+ * Authors: Ross Biro
+ * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ * Corey Minyard <wf-rch!minyard@relay.EU.net>
+ * Donald J. Becker, <becker@cesdis.gsfc.nasa.gov>
+ * Alan Cox, <Alan.Cox@linux.org>
+ * Bjorn Ekwall. <bj0rn@blox.se>
+ * Pekka Riikonen <priikone@poseidon.pspt.fi>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ *
+ * Moved to /usr/include/linux for NET3
+ */
+#ifndef _LINUX_NETDEVICE_H
+#define _LINUX_NETDEVICE_H
+
+/*
+ * Network device statistics. Akin to the 2.0 ether stats but
+ * with byte counters.
+ */
+
+struct net_device_stats {
+ unsigned long rx_packets; /* total packets received */
+ unsigned long tx_packets; /* total packets transmitted */
+ unsigned long rx_bytes; /* total bytes received */
+ unsigned long tx_bytes; /* total bytes transmitted */
+ unsigned long rx_errors; /* bad packets received */
+ unsigned long tx_errors; /* packet transmit problems */
+ unsigned long rx_dropped; /* no space in linux buffers */
+ unsigned long tx_dropped; /* no space available in linux */
+ unsigned long multicast; /* multicast packets received */
+ unsigned long collisions;
+
+ /* detailed rx_errors: */
+ unsigned long rx_length_errors;
+ unsigned long rx_over_errors; /* receiver ring buff overflow */
+ unsigned long rx_crc_errors; /* recved pkt with crc error */
+ unsigned long rx_frame_errors; /* recv'd frame alignment error */
+ unsigned long rx_fifo_errors; /* recv'r fifo overrun */
+ unsigned long rx_missed_errors; /* receiver missed packet */
+
+ /* detailed tx_errors */
+ unsigned long tx_aborted_errors;
+ unsigned long tx_carrier_errors;
+ unsigned long tx_fifo_errors;
+ unsigned long tx_heartbeat_errors;
+ unsigned long tx_window_errors;
+
+ /* for cslip etc */
+ unsigned long rx_compressed;
+ unsigned long tx_compressed;
+};
+
+#endif /* _LINUX_NETDEVICE_H */
diff --git a/include/net.h b/include/net.h
index e07b643705..b121fbbdef 100644
--- a/include/net.h
+++ b/include/net.h
@@ -436,7 +436,7 @@ extern ushort NetOurNativeVLAN; /* Our Native VLAN */
extern int NetRestartWrap; /* Tried all network devices */
enum proto_t {
- BOOTP, RARP, ARP, TFTPGET, DHCP, PING, DNS, NFS, CDP, NETCONS, SNTP,
+ BOOTP, RARP, ARP, TFTPGET, DHCP, DHCPSERVER, PING, DNS, NFS, CDP, NETCONS, SNTP,
TFTPSRV, TFTPPUT, LINKLOCAL
};
@@ -559,7 +559,8 @@ static inline __attribute__((always_inline)) int eth_is_on_demand_init(void)
#ifdef CONFIG_NETCONSOLE
extern enum proto_t net_loop_last_protocol;
- return net_loop_last_protocol != NETCONS;
+ return ( (net_loop_last_protocol != NETCONS) &&
+ (net_loop_last_protocol != DHCPSERVER) );
#else
return 1;
#endif
@@ -699,5 +700,7 @@ extern unsigned int random_port(void);
extern int update_tftp(ulong addr);
/**********************************************************************/
+extern IPaddr_t NetUSBdevIP;
+extern IPaddr_t NetUSBhostIP;
#endif /* __NET_H__ */
diff --git a/net/bootp.c b/net/bootp.c
index c3957ed17e..3ce754ac39 100644
--- a/net/bootp.c
+++ b/net/bootp.c
@@ -39,6 +39,10 @@
ulong BootpID;
ulong BootpIDlist[TIMEOUT_COUNT];
int BootpTry;
+extern unsigned dhcpserver;
+IPaddr_t NetUSBdevIP;
+IPaddr_t NetUSBhostIP;
+IPaddr_t NetUSBnetmaskIP;
#if defined(CONFIG_CMD_DHCP)
static dhcp_state_t dhcp_state = INIT;
@@ -74,7 +78,7 @@ static int BootpIDCheck(ulong ID)
if (BootpIDlist[i] == ID)
{
BootpID = ID;
- debug("ID match: %x\n", ID);
+ debug("ID match: %lx\n", ID);
return 0;
}
}
@@ -86,13 +90,18 @@ static int BootpCheckPkt(uchar *pkt, unsigned dest, unsigned src, unsigned len)
struct Bootp_t *bp = (struct Bootp_t *) pkt;
int retval = 0;
- if (dest != PORT_BOOTPC || src != PORT_BOOTPS)
+ if (dhcpserver) {
+ if (dest != PORT_BOOTPS || src != PORT_BOOTPC)
+ retval = -1;
+ }
+ else if (dest != PORT_BOOTPC || src != PORT_BOOTPS)
retval = -1;
else if (len < sizeof(struct Bootp_t) - OPT_FIELD_SIZE)
retval = -2;
else if (bp->bp_op != OP_BOOTREQUEST &&
bp->bp_op != OP_BOOTREPLY &&
bp->bp_op != DHCP_OFFER &&
+ bp->bp_op != DHCP_DISCOVER &&
bp->bp_op != DHCP_ACK &&
bp->bp_op != DHCP_NAK)
retval = -3;
@@ -834,6 +843,154 @@ static int DhcpMessageType(unsigned char *popt)
return -1;
}
+static void DhcpPrintPkt(struct Bootp_t *bp, int len)
+{
+#ifdef DEBUG
+ int i;
+ char *ptr = bp;
+
+ for (i = 0; i < len; i++) {
+ if ((i % 25) == 0)
+ printf("\n");
+ printf("%02X ", ptr[i]);
+ }
+ printf("\n");
+#endif
+}
+
+static void DhcpRecvDiscoverPkt(struct Bootp_t *bp_discover, int len)
+{
+ uchar *pkt, *iphdr;
+ struct Bootp_t *bp;
+ int i, iplen, pktlen, eth_hdr_size;
+ uchar *ptr = (uchar *) bp_discover;
+
+ debug("DhcpRecvDiscoverPkt\n");
+
+ DhcpPrintPkt(bp_discover, len);
+
+/* Lets send out our DHCP OFFER
+ * We really dont have to look at the options that were passed in
+ * discover. We just return back 4 messages (below in decimal)
+ * 1. 53 = 0x35 (DHCP Message type) 1 (1 byte) X (DHCP Offer(2) or DHCP Ack(5))
+ * 2. 54 = 0x36 (Server identifier) 4 (4 bytes) Server IP addresss
+ * 3. 51 = 0x33 (IP address lease time) 4 (4 bytes) 85536 (24 hours)
+ * 4. 1 (Subnet mask) 4 (4 bytes) 255.255.255.0
+ */
+ pkt = NetTxPacket;
+ memset((void *)pkt, 0, PKTSIZE);
+
+ eth_hdr_size = NetSetEther(pkt, NetBcastAddr, PROT_IP);
+ pkt += eth_hdr_size;
+
+ iphdr = pkt; /* We'll need this later to set proper pkt size */
+ pkt += IP_UDP_HDR_SIZE;
+
+ bp = (struct Bootp_t *)pkt;
+ bp->bp_op = OP_BOOTREPLY;
+ bp->bp_htype = HWT_ETHER;
+ bp->bp_hlen = HWL_ETHER;
+ bp->bp_hops = 0;
+ bp->bp_secs = bp_discover->bp_secs;
+
+ memcpy(&bp->bp_chaddr, &bp_discover->bp_chaddr, 6);
+
+ memcpy(&bp->bp_id, &bp_discover->bp_id, 4);
+
+ NetCopyIP(&bp->bp_siaddr, &NetUSBdevIP);
+ NetCopyIP(&bp->bp_yiaddr, &NetUSBhostIP);
+
+ /* Copy the magic */
+ memcpy(&bp->bp_vend, &bp_discover->bp_vend, 4);
+
+ bp->bp_vend[4] = 0x35;
+ bp->bp_vend[5] = 0x01;
+ bp->bp_vend[6] = DHCP_OFFER;
+ bp->bp_vend[7] = 0x36; /* DHCP Server IP */
+ bp->bp_vend[8] = 0x04;
+ NetCopyIP(&bp->bp_vend[9], &NetUSBdevIP);
+ bp->bp_vend[13] = 0x33; /* Lease time */
+ bp->bp_vend[14] = 0x04;
+ bp->bp_vend[15] = 0x00; /* 00 01 51 89 */
+ bp->bp_vend[16] = 0x01;
+ bp->bp_vend[17] = 0x51;
+ bp->bp_vend[18] = 0x89;
+ bp->bp_vend[19] = 0x01; /* subnet mask */
+ bp->bp_vend[20] = 0x04;
+ NetCopyIP(&bp->bp_vend[21], &NetUSBnetmaskIP);
+ bp->bp_vend[25] = 0xFF; /* End option marker */
+
+ iplen = BOOTP_HDR_SIZE - OPT_FIELD_SIZE + 26;
+ debug("Sending DHCP Offer packet\n");
+ DhcpPrintPkt(bp, iplen);
+ pktlen = eth_hdr_size + IP_UDP_HDR_SIZE + iplen;
+ net_set_udp_header(iphdr, 0xFFFFFFFFL, PORT_BOOTPC, PORT_BOOTPS, iplen);
+ NetSendPacket(NetTxPacket, pktlen);
+}
+
+static void DhcpRecvRequestPkt(struct Bootp_t *bp_request, int len)
+{
+ uchar *pkt, *iphdr;
+ struct Bootp_t *bp;
+ int i, iplen, pktlen, eth_hdr_size;
+ uchar *ptr = (uchar *) bp_request;
+
+ debug("DhcpRecvRequestPkt\n");
+
+ DhcpPrintPkt(bp_request, len);
+
+ /* Lets send out our DHCP ACK */
+ pkt = NetTxPacket;
+ memset((void *)pkt, 0, PKTSIZE);
+
+ eth_hdr_size = NetSetEther(pkt, NetBcastAddr, PROT_IP);
+ pkt += eth_hdr_size;
+
+ iphdr = pkt; /* We'll need this later to set proper pkt size */
+ pkt += IP_UDP_HDR_SIZE;
+
+ bp = (struct Bootp_t *)pkt;
+ bp->bp_op = OP_BOOTREPLY;
+ bp->bp_htype = HWT_ETHER;
+ bp->bp_hlen = HWL_ETHER;
+ bp->bp_hops = 0;
+ bp->bp_secs = bp_request->bp_secs;
+
+ memcpy(&bp->bp_chaddr, &bp_request->bp_chaddr, 6);
+
+ memcpy(&bp->bp_id, &bp_request->bp_id, 4);
+
+ NetCopyIP(&bp->bp_siaddr, &NetUSBdevIP);
+ NetCopyIP(&bp->bp_yiaddr, &NetUSBhostIP);
+
+ /* Copy the magic */
+ memcpy(&bp->bp_vend, &bp_request->bp_vend, 4);
+
+ bp->bp_vend[4] = 0x35;
+ bp->bp_vend[5] = 0x01;
+ bp->bp_vend[6] = DHCP_ACK;
+ bp->bp_vend[7] = 0x36; /* DHCP Server IP */
+ bp->bp_vend[8] = 0x04;
+ NetCopyIP(&bp->bp_vend[9], &NetUSBdevIP);
+ bp->bp_vend[13] = 0x33; /* Lease time */
+ bp->bp_vend[14] = 0x04;
+ bp->bp_vend[15] = 0x00; /* 00 01 51 89 */
+ bp->bp_vend[16] = 0x01;
+ bp->bp_vend[17] = 0x51;
+ bp->bp_vend[18] = 0x89;
+ bp->bp_vend[19] = 0x01; /* subnet mask */
+ bp->bp_vend[20] = 0x04;
+ NetCopyIP(&bp->bp_vend[21], &NetUSBnetmaskIP);
+ bp->bp_vend[25] = 0xFF; /* End option marker */
+
+ iplen = BOOTP_HDR_SIZE - OPT_FIELD_SIZE + 26;
+ debug("Sending DHCP Ack packet\n");
+ DhcpPrintPkt(bp, iplen);
+ pktlen = eth_hdr_size + IP_UDP_HDR_SIZE + iplen;
+ net_set_udp_header(iphdr, 0xFFFFFFFFL, PORT_BOOTPC, PORT_BOOTPS, iplen);
+ NetSendPacket(NetTxPacket, pktlen);
+}
+
static void DhcpSendRequestPkt(struct Bootp_t *bp_offer)
{
uchar *pkt, *iphdr;
@@ -904,9 +1061,6 @@ DhcpHandler(uchar *pkt, unsigned dest, IPaddr_t sip, unsigned src,
{
struct Bootp_t *bp = (struct Bootp_t *)pkt;
- debug("DHCPHandler: got packet: (src=%d, dst=%d, len=%d) state: %d\n",
- src, dest, len, dhcp_state);
-
/* Filter out pkts we don't want */
if (BootpCheckPkt(pkt, dest, src, len))
return;
@@ -966,6 +1120,35 @@ DhcpHandler(uchar *pkt, unsigned dest, IPaddr_t sip, unsigned src,
case BOUND:
/* DHCP client bound to address */
break;
+ case WAITFORDISCOVER:
+ /* Got a DISCOVER packet - send response and set */
+ /* state to WAITFORREQUEST */
+ /* We can also get a direct REQUEST packet */
+ if (DhcpMessageType((u8 *)bp->bp_vend) == DHCP_REQUEST)
+ {
+ debug("REQUEST packet received\n");
+ DhcpRecvRequestPkt(bp, len);
+ dhcpserver = 2;
+ net_set_state(NETLOOP_SUCCESS);
+ break;
+ }
+ if (DhcpMessageType((u8 *)bp->bp_vend) != DHCP_DISCOVER)
+ break;
+ debug("DISCOVER packet received\n");
+ DhcpRecvDiscoverPkt(bp, len);
+ dhcp_state = WAITFORREQUEST;
+ break;
+
+ case WAITFORREQUEST:
+ /* Got a Request. Send an ACK packet */
+ if (DhcpMessageType((u8 *)bp->bp_vend) != DHCP_REQUEST)
+ break;
+ debug("REQUEST packet received\n");
+ DhcpRecvRequestPkt(bp, len);
+ dhcpserver = 2;
+ net_set_state(NETLOOP_SUCCESS);
+ break;
+
default:
puts("DHCP: INVALID STATE\n");
break;
@@ -977,4 +1160,46 @@ void DhcpRequest(void)
{
BootpRequest();
}
+
+/* Called from netconsole.c when dhcpserver is 1.
+ * We set dhcpserver to 3 as we have timed out.
+ */
+static void dhcpserver_to_handler(void)
+{
+ debug("\n%s: DHCP Server time out\n", __func__);
+ /* We set it to success so that it doesnt reinit the eth device */
+ net_set_state(NETLOOP_SUCCESS);
+ /* We set this to 3 to imply that a DHCP server failed. */
+ dhcpserver = 3;
+}
+
+int DhcpServer(void)
+{
+ int retval = -1;
+
+ net_init();
+
+ NetUSBdevIP = string_to_ip(CONFIG_USBNET_DEV_IP);
+ NetUSBhostIP = string_to_ip(CONFIG_USBNET_HOST_IP);
+ NetUSBnetmaskIP = string_to_ip(CONFIG_USBNET_DEV_NETMASK);
+
+ eth_set_last_protocol(DHCPSERVER);
+
+ dhcp_state = WAITFORDISCOVER;
+ net_set_udp_handler(DhcpHandler);
+
+/*
+ * Here we loop for some timeout to see if we do get a
+ * DISCOVER packet. If we don't we just return -1.
+ * We need to set timeout to about 10 seconds.
+ */
+ NetSetTimeout(10000, dhcpserver_to_handler);
+ NetLoop(DHCPSERVER);
+ if (dhcpserver == 3) {
+ debug("No DHCP Request received\n");
+ return -1;
+ }
+
+ return 0;
+}
#endif /* CONFIG_CMD_DHCP */
diff --git a/net/bootp.h b/net/bootp.h
index ecbcc4d509..1512cd93ae 100644
--- a/net/bootp.h
+++ b/net/bootp.h
@@ -78,7 +78,9 @@ typedef enum { INIT,
REQUESTING,
REBINDING,
BOUND,
- RENEWING } dhcp_state_t;
+ RENEWING,
+ WAITFORDISCOVER,
+ WAITFORREQUEST } dhcp_state_t;
#define DHCP_DISCOVER 1
#define DHCP_OFFER 2
diff --git a/net/net.c b/net/net.c
index f7cc29f039..faa3a7fb95 100644
--- a/net/net.c
+++ b/net/net.c
@@ -333,7 +333,8 @@ int NetLoop(enum proto_t protocol)
bootstage_mark_name(BOOTSTAGE_ID_ETH_START, "eth_start");
net_init();
- if (eth_is_on_demand_init() || protocol != NETCONS) {
+ if (eth_is_on_demand_init() || ((protocol != NETCONS) &&
+ (protocol != DHCPSERVER)) ) {
eth_halt();
eth_set_current();
if (eth_init(bd) < 0) {
@@ -389,6 +390,10 @@ restart:
NetOurIP = 0;
DhcpRequest(); /* Basically same as BOOTP */
break;
+
+ case DHCPSERVER:
+ debug("NetLoop: DHCPSERVER case\n");
+ break;
#endif
case BOOTP:
@@ -543,7 +548,7 @@ restart:
setenv_hex("filesize", NetBootFileXferSize);
setenv_hex("fileaddr", load_addr);
}
- if (protocol != NETCONS)
+ if ( (protocol != NETCONS) && (protocol != DHCPSERVER) )
eth_halt();
else
eth_halt_state_only();
diff --git a/tools/nc.odroid b/tools/nc.odroid
new file mode 100644
index 0000000000..b83ad8ca50
--- /dev/null
+++ b/tools/nc.odroid
@@ -0,0 +1,31 @@
+#!/bin/sh
+
+boardip=10.10.10.11
+hostip=10.10.10.10
+interface=usb0
+port=6666
+
+echo "Please connect the the OTG port of the Odroid to your host PC"
+echo "Power on the Odroid"
+echo ""
+while [ 1 ];
+do
+ good=`ifconfig $interface 2> /dev/null | grep $hostip | wc -l`
+ if [ "$good" = "1" ];
+ then
+ echo "Board Connectivity established - Enjoy netconsole over CDC ETH"
+ echo "--------------------------------------------------------------"
+ break;
+ fi
+ sleep 1
+done
+
+trap "stty icanon echo intr ^C" 0 2 3 5 10 13 15
+echo "NOTE: the interrupt signal (normally ^C) has been remapped to ^T"
+
+stty -icanon -echo intr ^T
+(
+ nc -u -p $port $boardip $port
+)
+pid=$!
+kill ${pid} 2>/dev/null