summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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