summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2010-06-17 08:29:09 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2010-06-17 08:29:09 +0200
commitf7c02aea7b45474126b4723dfeb2581b0fd55447 (patch)
tree891c5d2c71f0c00bbe35235d0e1a8158e567a019
parenta81786a053ed1f08aab8d70d28dbf33691ab7a37 (diff)
parentc5de3fdcce291a9049a03f86f0553032f5068916 (diff)
downloadbarebox-f7c02aea7b45474126b4723dfeb2581b0fd55447.tar.gz
barebox-f7c02aea7b45474126b4723dfeb2581b0fd55447.tar.xz
Merge branch 'net' into next
-rw-r--r--Documentation/users_manual.dox1
-rw-r--r--Doxyfile3
-rw-r--r--Makefile2
-rw-r--r--arch/arm/configs/eukrea_cpuimx25_defconfig23
-rw-r--r--arch/arm/configs/eukrea_cpuimx27_defconfig2
-rw-r--r--arch/arm/cpu/cpu.c15
-rw-r--r--arch/arm/cpu/start.c17
-rw-r--r--arch/arm/mach-imx/include/mach/imx27-regs.h3
-rw-r--r--board/eukrea_cpuimx25/env/bin/init3
-rw-r--r--board/eukrea_cpuimx25/eukrea_cpuimx25.c2
-rw-r--r--board/eukrea_cpuimx27/eukrea_cpuimx27.c6
-rw-r--r--board/freescale-mx25-3-stack/3stack.c2
-rw-r--r--board/freescale-mx35-3-stack/flash_header.c2
-rw-r--r--board/pcm043/lowlevel.c2
-rw-r--r--commands/net.c38
-rw-r--r--common/console.c40
-rw-r--r--common/misc.c7
-rw-r--r--drivers/nand/nand.c7
-rw-r--r--drivers/net/at91_ether.c2
-rw-r--r--drivers/net/cs8900.c2
-rw-r--r--drivers/net/dm9000.c2
-rw-r--r--drivers/net/ep93xx.c4
-rw-r--r--drivers/net/fec_imx.c2
-rw-r--r--drivers/net/fec_mpc5200.c2
-rw-r--r--drivers/net/macb.c2
-rw-r--r--drivers/net/netx_eth.c2
-rw-r--r--drivers/net/smc91111.c2
-rw-r--r--drivers/net/smc911x.c2
-rw-r--r--drivers/net/tap.c2
-rw-r--r--drivers/net/usb/asix.c2
-rw-r--r--drivers/net/usb/usbnet.c2
-rw-r--r--drivers/video/fb.c21
-rw-r--r--drivers/video/imx.c17
-rw-r--r--include/console.h6
-rw-r--r--include/driver.h2
-rw-r--r--include/fb.h2
-rw-r--r--include/net.h456
-rw-r--r--include/param.h15
-rw-r--r--lib/driver.c12
-rw-r--r--lib/parameter.c195
-rw-r--r--net/Kconfig15
-rw-r--r--net/Makefile3
-rw-r--r--net/dhcp.c491
-rw-r--r--net/dns.c264
-rw-r--r--net/eth.c98
-rw-r--r--net/net.c1237
-rw-r--r--net/netconsole.c228
-rw-r--r--net/nfs.c716
-rw-r--r--net/ping.c152
-rw-r--r--net/rarp.c101
-rw-r--r--net/sntp.h61
-rw-r--r--net/tftp.c271
52 files changed, 2226 insertions, 2340 deletions
diff --git a/Documentation/users_manual.dox b/Documentation/users_manual.dox
index 5467bee475..cd2b99cd41 100644
--- a/Documentation/users_manual.dox
+++ b/Documentation/users_manual.dox
@@ -11,5 +11,6 @@ work easier.
@li @subpage command_reference
@li @subpage partitions
@li @subpage x86_bootloader
+@li @subpage net_netconsole
*/
diff --git a/Doxyfile b/Doxyfile
index 94dd6ae0df..40bcb2f97c 100644
--- a/Doxyfile
+++ b/Doxyfile
@@ -485,7 +485,8 @@ INPUT = Documentation \
common \
board \
lib \
- scripts/setupmbr
+ scripts/setupmbr \
+ net
# This tag can be used to specify the character encoding of the source files that
# doxygen parses. Internally doxygen uses the UTF-8 encoding, which is also the default
diff --git a/Makefile b/Makefile
index 71d66f7f90..d17ca47ff9 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
VERSION = 2010
-PATCHLEVEL = 05
+PATCHLEVEL = 06
SUBLEVEL = 0
EXTRAVERSION =
NAME = Amissive Actinocutious Kiwi
diff --git a/arch/arm/configs/eukrea_cpuimx25_defconfig b/arch/arm/configs/eukrea_cpuimx25_defconfig
index 81f9c80a3c..574d32292d 100644
--- a/arch/arm/configs/eukrea_cpuimx25_defconfig
+++ b/arch/arm/configs/eukrea_cpuimx25_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# barebox version: 2010.03.0
-# Fri Mar 19 11:12:11 2010
+# barebox version: 2010.05.0
+# Wed Jun 2 01:04:00 2010
#
# CONFIG_BOARD_LINKER_SCRIPT is not set
CONFIG_GENERIC_LINKER_SCRIPT=y
@@ -88,19 +88,20 @@ CONFIG_MALLOC_SIZE=0x1000000
# CONFIG_EXPERIMENTAL is not set
CONFIG_MACH_HAS_LOWLEVEL_INIT=y
CONFIG_MACH_DO_LOWLEVEL_INIT=y
-CONFIG_PROMPT="barebox:"
+CONFIG_PROMPT="cpuimx25:"
CONFIG_BAUDRATE=115200
-# CONFIG_LONGHELP is not set
+CONFIG_LONGHELP=y
CONFIG_CBSIZE=1024
CONFIG_MAXARGS=16
CONFIG_SHELL_HUSH=y
# CONFIG_SHELL_SIMPLE is not set
CONFIG_GLOB=y
CONFIG_PROMPT_HUSH_PS2="cpuimx25>"
+CONFIG_HUSH_FANCY_PROMPT=y
CONFIG_CMDLINE_EDITING=y
CONFIG_AUTO_COMPLETE=y
CONFIG_DYNAMIC_CRC_TABLE=y
-# CONFIG_ERRNO_MESSAGES is not set
+CONFIG_ERRNO_MESSAGES=y
CONFIG_TIMESTAMP=y
CONFIG_CONSOLE_FULL=y
CONFIG_CONSOLE_ACTIVATE_FIRST=y
@@ -153,6 +154,7 @@ CONFIG_CMD_UMOUNT=y
#
CONFIG_CMD_CLEAR=y
CONFIG_CMD_ECHO=y
+CONFIG_CMD_ECHO_E=y
#
# memory
@@ -172,9 +174,9 @@ CONFIG_CMD_FLASH=y
# booting
#
CONFIG_CMD_BOOTM=y
-# CONFIG_CMD_BOOTM_ZLIB is not set
-# CONFIG_CMD_BOOTM_BZLIB is not set
-# CONFIG_CMD_BOOTM_SHOW_TYPE is not set
+CONFIG_CMD_BOOTM_ZLIB=y
+CONFIG_CMD_BOOTM_BZLIB=y
+CONFIG_CMD_BOOTM_SHOW_TYPE=y
CONFIG_CMD_BOOTZ=y
CONFIG_CMD_BOOTU=y
# CONFIG_CMD_LINUX16 is not set
@@ -188,6 +190,7 @@ CONFIG_CMD_HELP=y
CONFIG_CMD_DEVINFO=y
CONFIG_CMD_BMP=y
CONFIG_CMD_GPIO=y
+CONFIG_CMD_UNLZO=y
CONFIG_NET=y
CONFIG_NET_DHCP=y
# CONFIG_NET_RARP is not set
@@ -243,5 +246,9 @@ CONFIG_DRIVER_VIDEO_IMX=y
# CONFIG_FS_CRAMFS is not set
CONFIG_FS_RAMFS=y
CONFIG_FS_DEVFS=y
+CONFIG_ZLIB=y
+CONFIG_BZLIB=y
CONFIG_CRC32=y
# CONFIG_GENERIC_FIND_NEXT_BIT is not set
+CONFIG_PROCESS_ESCAPE_SEQUENCE=y
+CONFIG_LZO_DECOMPRESS=y
diff --git a/arch/arm/configs/eukrea_cpuimx27_defconfig b/arch/arm/configs/eukrea_cpuimx27_defconfig
index 3b92c37ff2..a1cf1adb74 100644
--- a/arch/arm/configs/eukrea_cpuimx27_defconfig
+++ b/arch/arm/configs/eukrea_cpuimx27_defconfig
@@ -92,7 +92,7 @@ CONFIG_HAVE_CONFIGURABLE_MEMORY_LAYOUT=y
CONFIG_MEMORY_LAYOUT_DEFAULT=y
# CONFIG_MEMORY_LAYOUT_FIXED is not set
CONFIG_STACK_SIZE=0x8000
-CONFIG_MALLOC_SIZE=0x400000
+CONFIG_MALLOC_SIZE=0x800000
# CONFIG_BROKEN is not set
# CONFIG_EXPERIMENTAL is not set
CONFIG_MACH_HAS_LOWLEVEL_INIT=y
diff --git a/arch/arm/cpu/cpu.c b/arch/arm/cpu/cpu.c
index fbc91aabf2..2b36a793dc 100644
--- a/arch/arm/cpu/cpu.c
+++ b/arch/arm/cpu/cpu.c
@@ -75,12 +75,19 @@ void arch_shutdown(void)
int i;
#ifdef CONFIG_MMU
+ /* nearly the same as below, but this could also disable
+ * second level cache.
+ */
mmu_disable();
+#else
+ asm volatile (
+ "bl __mmu_cache_flush;"
+ "bl __mmu_cache_off;"
+ :
+ :
+ : "r0", "r1", "r2", "r3", "r6", "r10", "r12", "cc", "memory"
+ );
#endif
-
- /* flush I/D-cache */
- i = 0;
- asm ("mcr p15, 0, %0, c7, c7, 0": :"r" (i));
}
/**
diff --git a/arch/arm/cpu/start.c b/arch/arm/cpu/start.c
index 67d54a6a76..eea7dcfa3c 100644
--- a/arch/arm/cpu/start.c
+++ b/arch/arm/cpu/start.c
@@ -81,21 +81,24 @@ void __naked __bare_init reset(void)
*/
void __naked __bare_init board_init_lowlevel_return(void)
{
- uint32_t r;
+ uint32_t r, addr;
+
+ /*
+ * Get runtime address of this function. Do not
+ * put any code above this.
+ */
+ __asm__ __volatile__("1: adr %0, 1b":"=r"(addr));
/* Setup the stack */
r = STACK_BASE + STACK_SIZE - 16;
__asm__ __volatile__("mov sp, %0" : : "r"(r));
- /* Get runtime address of this function */
- __asm__ __volatile__("adr %0, 0":"=r"(r));
-
/* Get start of binary image */
- r -= (uint32_t)&board_init_lowlevel_return - TEXT_BASE;
+ addr -= (uint32_t)&board_init_lowlevel_return - TEXT_BASE;
/* relocate to link address if necessary */
- if (r != TEXT_BASE)
- memcpy((void *)TEXT_BASE, (void *)r,
+ if (addr != TEXT_BASE)
+ memcpy((void *)TEXT_BASE, (void *)addr,
(unsigned int)&__bss_start - TEXT_BASE);
/* clear bss */
diff --git a/arch/arm/mach-imx/include/mach/imx27-regs.h b/arch/arm/mach-imx/include/mach/imx27-regs.h
index 6c31ccd914..4e2261261e 100644
--- a/arch/arm/mach-imx/include/mach/imx27-regs.h
+++ b/arch/arm/mach-imx/include/mach/imx27-regs.h
@@ -22,6 +22,7 @@
#define IMX_TIM5_BASE (0x1a000 + IMX_IO_BASE)
#define IMX_UART5_BASE (0x1b000 + IMX_IO_BASE)
#define IMX_UART6_BASE (0x1c000 + IMX_IO_BASE)
+#define IMX_I2C2_BASE (0x1d000 + IMX_IO_BASE)
#define IMX_TIM6_BASE (0x1f000 + IMX_IO_BASE)
#define IMX_AIPI2_BASE (0x20000 + IMX_IO_BASE)
#define IMX_PLL_BASE (0x27000 + IMX_IO_BASE)
@@ -309,6 +310,8 @@
#define PE13_PF_UART1_RXD (GPIO_PORTE | GPIO_IN | GPIO_PF | 13)
#define PE14_PF_UART1_CTS (GPIO_PORTE | GPIO_OUT | GPIO_PF | 14)
#define PE15_PF_UART1_RTS (GPIO_PORTE | GPIO_IN | GPIO_PF | 15)
+#define PC5_PF_I2C2_DATA (GPIO_PORTC | GPIO_OUT | GPIO_PF | 5)
+#define PC6_PF_I2C2_CLK (GPIO_PORTC | GPIO_OUT | GPIO_PF | 6)
#define PC7_PF_USBOTG_DATA5 (GPIO_PORTC | GPIO_PF | GPIO_OUT | 7)
#define PC8_PF_USBOTG_DATA6 (GPIO_PORTC | GPIO_PF | GPIO_OUT | 8)
#define PC9_PF_USBOTG_DATA0 (GPIO_PORTC | GPIO_PF | GPIO_OUT | 9)
diff --git a/board/eukrea_cpuimx25/env/bin/init b/board/eukrea_cpuimx25/env/bin/init
index 8bcc732a40..335d7ae579 100644
--- a/board/eukrea_cpuimx25/env/bin/init
+++ b/board/eukrea_cpuimx25/env/bin/init
@@ -14,6 +14,9 @@ fi
if [ -f /env/logo.bmp ]; then
bmp /env/logo.bmp
+elif [ -f /env/logo.bmp.lzo ]; then
+ unlzo /env/logo.bmp.lzo /logo.bmp
+ bmp /logo.bmp
fi
if [ -z $eth0.ethaddr ]; then
diff --git a/board/eukrea_cpuimx25/eukrea_cpuimx25.c b/board/eukrea_cpuimx25/eukrea_cpuimx25.c
index 8cbbc4fc57..b19efcc9d3 100644
--- a/board/eukrea_cpuimx25/eukrea_cpuimx25.c
+++ b/board/eukrea_cpuimx25/eukrea_cpuimx25.c
@@ -63,8 +63,6 @@ struct imx_dcd_entry __dcd_entry_0x400 dcd_entry[] = {
{ .ptr_type = 4, .addr = 0x53f80008, .val = 0x20034000, },
};
-#define APP_DEST 0x80000000
-
struct imx_flash_header __flash_header_0x400 eukrea_cpuimx25_header = {
.app_code_jump_vector = TEXT_BASE + 0x2000,
.app_code_barker = APP_CODE_BARKER,
diff --git a/board/eukrea_cpuimx27/eukrea_cpuimx27.c b/board/eukrea_cpuimx27/eukrea_cpuimx27.c
index c849022af6..e40c260320 100644
--- a/board/eukrea_cpuimx27/eukrea_cpuimx27.c
+++ b/board/eukrea_cpuimx27/eukrea_cpuimx27.c
@@ -341,18 +341,20 @@ console_initcall(eukrea_cpuimx27_console_init);
static int eukrea_cpuimx27_late_init(void)
{
+#ifdef CONFIG_DRIVER_I2C_LP3972
struct i2c_client *client;
u8 reg[1];
-
+#endif
console_flush();
register_device(&fec_dev);
+#ifdef CONFIG_DRIVER_I2C_LP3972
client = lp3972_get_client();
if (!client)
return -ENODEV;
reg[0] = 0xa0;
i2c_write_reg(client, 0x39, reg, sizeof(reg));
-
+#endif
return 0;
}
diff --git a/board/freescale-mx25-3-stack/3stack.c b/board/freescale-mx25-3-stack/3stack.c
index 372fbc6d37..a77a02d498 100644
--- a/board/freescale-mx25-3-stack/3stack.c
+++ b/board/freescale-mx25-3-stack/3stack.c
@@ -44,7 +44,7 @@ extern unsigned long _stext;
void __naked __flash_header_start go(void)
{
- __asm__ __volatile__("b _start\n");
+ __asm__ __volatile__("b exception_vectors\n");
}
struct imx_dcd_entry __dcd_entry_0x400 dcd_entry[] = {
diff --git a/board/freescale-mx35-3-stack/flash_header.c b/board/freescale-mx35-3-stack/flash_header.c
index 968a948a8d..171c499a6d 100644
--- a/board/freescale-mx35-3-stack/flash_header.c
+++ b/board/freescale-mx35-3-stack/flash_header.c
@@ -5,7 +5,7 @@ extern unsigned long _stext;
void __naked __flash_header_start go(void)
{
- __asm__ __volatile__("b _start\n");
+ __asm__ __volatile__("b exception_vectors\n");
}
struct imx_dcd_entry __dcd_entry_0x400 dcd_entry[] = {
diff --git a/board/pcm043/lowlevel.c b/board/pcm043/lowlevel.c
index d4059db008..9eff5a6713 100644
--- a/board/pcm043/lowlevel.c
+++ b/board/pcm043/lowlevel.c
@@ -194,7 +194,7 @@ void __bare_init __naked board_init_lowlevel(void)
#ifdef CONFIG_NAND_IMX_BOOT
/* skip NAND boot if not running from NFC space */
r = get_pc();
- if (r < IMX_NFC_BASE && r > IMX_NFC_BASE + 0x800)
+ if (r < IMX_NFC_BASE || r > IMX_NFC_BASE + 0x800)
board_init_lowlevel_return();
src = (unsigned int *)IMX_NFC_BASE;
diff --git a/commands/net.c b/commands/net.c
index 815a566a2b..938463c7c4 100644
--- a/commands/net.c
+++ b/commands/net.c
@@ -35,44 +35,6 @@
#include <errno.h>
#include <libbb.h>
-void netboot_update_env(void)
-{
- struct eth_device *eth_current = eth_get_current();
- char tmp[22];
-
- if (NetOurGatewayIP)
- dev_set_param_ip(&eth_current->dev, "gateway", NetOurGatewayIP);
-
- if (NetOurSubnetMask)
- dev_set_param_ip(&eth_current->dev, "netmask", NetOurSubnetMask);
-
-
- if (NetOurHostName[0])
- setenv ("hostname", NetOurHostName);
-
- if (NetOurRootPath[0])
- setenv ("rootpath", NetOurRootPath);
-
- if (NetOurIP)
- dev_set_param_ip(&eth_current->dev, "ipaddr", NetOurIP);
-
- if (NetServerIP)
- dev_set_param_ip(&eth_current->dev, "serverip", NetServerIP);
-
- if (NetOurDNSIP) {
- ip_to_string (NetOurDNSIP, tmp);
- setenv ("dnsip", tmp);
- }
-#ifdef CONFIG_BOOTP_DNS2
- if (NetOurDNS2IP) {
- ip_to_string (NetOurDNS2IP, tmp);
- setenv ("dnsip2", tmp);
- }
-#endif
- if (NetOurNISDomain[0])
- setenv ("domain", NetOurNISDomain);
-}
-
#ifdef CONFIG_NET_RARP
extern void RarpRequest(void);
diff --git a/common/console.c b/common/console.c
index d3d31f7898..7199d9afb8 100644
--- a/common/console.c
+++ b/common/console.c
@@ -57,26 +57,32 @@ static int console_std_set(struct device_d *dev, struct param_d *param,
const char *val)
{
struct console_device *cdev = dev->type_data;
+ char active[4];
unsigned int flag = 0, i = 0;
+ if (!val)
+ dev_param_set_generic(dev, param, NULL);
+
if (strchr(val, 'i') && cdev->f_caps & CONSOLE_STDIN) {
- cdev->active[i++] = 'i';
+ active[i++] = 'i';
flag |= CONSOLE_STDIN;
}
if (strchr(val, 'o') && cdev->f_caps & CONSOLE_STDOUT) {
- cdev->active[i++] = 'o';
+ active[i++] = 'o';
flag |= CONSOLE_STDOUT;
}
if (strchr(val, 'e') && cdev->f_caps & CONSOLE_STDERR) {
- cdev->active[i++] = 'e';
+ active[i++] = 'e';
flag |= CONSOLE_STDERR;
}
- cdev->active[i] = 0;
+ active[i] = 0;
cdev->f_active = flag;
+ dev_param_set_generic(dev, param, active);
+
return 0;
}
@@ -85,8 +91,12 @@ static int console_baudrate_set(struct device_d *dev, struct param_d *param,
{
struct console_device *cdev = dev->type_data;
int baudrate;
+ char baudstr[16];
unsigned char c;
+ if (!val)
+ dev_param_set_generic(dev, param, NULL);
+
baudrate = simple_strtoul(val, NULL, 10);
if (cdev->f_active) {
@@ -101,7 +111,8 @@ static int console_baudrate_set(struct device_d *dev, struct param_d *param,
} else
cdev->setbrg(cdev, baudrate);
- sprintf(cdev->baudrate_string, "%d", baudrate);
+ sprintf(baudstr, "%d", baudrate);
+ dev_param_set_generic(dev, param, baudstr);
return 0;
}
@@ -129,29 +140,20 @@ int console_register(struct console_device *newcdev)
register_device(dev);
if (newcdev->setbrg) {
- newcdev->baudrate_param.set = console_baudrate_set;
- newcdev->baudrate_param.name = "baudrate";
- sprintf(newcdev->baudrate_string, "%d",
- CONFIG_BAUDRATE);
- console_baudrate_set(dev, &newcdev->baudrate_param,
- newcdev->baudrate_string);
- newcdev->baudrate_param.value = newcdev->baudrate_string;
- dev_add_param(dev, &newcdev->baudrate_param);
+ dev_add_param(dev, "baudrate", console_baudrate_set, NULL, 0);
+ dev_set_param(dev, "baudrate", "115200");
}
- newcdev->active_param.set = console_std_set;
- newcdev->active_param.name = "active";
- newcdev->active_param.value = newcdev->active;
- dev_add_param(dev, &newcdev->active_param);
+ dev_add_param(dev, "active", console_std_set, NULL, 0);
initialized = CONSOLE_INIT_FULL;
#ifdef CONFIG_CONSOLE_ACTIVATE_ALL
- console_std_set(dev, &newcdev->active_param, "ioe");
+ dev_set_param(dev, "active", "ioe");
#endif
#ifdef CONFIG_CONSOLE_ACTIVATE_FIRST
if (list_empty(&console_list)) {
first = 1;
- console_std_set(dev, &newcdev->active_param, "ioe");
+ dev_set_param(dev, "active", "ioe");
}
#endif
diff --git a/common/misc.c b/common/misc.c
index b3292d3120..7edf536bab 100644
--- a/common/misc.c
+++ b/common/misc.c
@@ -56,6 +56,10 @@ const char *strerror(int errnum)
case ENAMETOOLONG : str = "File name too long"; break;
case ENOSYS : str = "Function not implemented"; break;
case ENOTEMPTY : str = "Directory not empty"; break;
+ case EHOSTUNREACH : str = "No route to host"; break;
+ case EINTR : str = "Interrupted system call"; break;
+ case ENETUNREACH : str = "Network is unreachable"; break;
+ case ENETDOWN : str = "Network is down"; break;
#if 0 /* These are probably not needed */
case ENOTBLK : str = "Block device required"; break;
case EFBIG : str = "File too large"; break;
@@ -79,8 +83,6 @@ const char *strerror(int errnum)
case EAFNOSUPPORT : str = "Address family not supported by protocol"; break;
case EADDRINUSE : str = "Address already in use"; break;
case EADDRNOTAVAIL : str = "Cannot assign requested address"; break;
- case ENETDOWN : str = "Network is down"; break;
- case ENETUNREACH : str = "Network is unreachable"; break;
case ENETRESET : str = "Network dropped connection because of reset"; break;
case ECONNABORTED : str = "Software caused connection abort"; break;
case ECONNRESET : str = "Connection reset by peer"; break;
@@ -88,7 +90,6 @@ const char *strerror(int errnum)
case ETIMEDOUT : str = "Connection timed out"; break;
case ECONNREFUSED : str = "Connection refused"; break;
case EHOSTDOWN : str = "Host is down"; break;
- case EHOSTUNREACH : str = "No route to host"; break;
case EALREADY : str = "Operation already in progress"; break;
case EINPROGRESS : str = "Operation now in progress"; break;
case ESTALE : str = "Stale NFS file handle"; break;
diff --git a/drivers/nand/nand.c b/drivers/nand/nand.c
index bcf52bd940..4927231c17 100644
--- a/drivers/nand/nand.c
+++ b/drivers/nand/nand.c
@@ -210,6 +210,7 @@ static struct file_operations nand_ops_oob = {
int add_mtd_device(struct mtd_info *mtd)
{
struct nand_chip *chip = mtd->priv;
+ char str[16];
strcpy(mtd->class_dev.name, "nand");
register_device(&mtd->class_dev);
@@ -220,10 +221,8 @@ int add_mtd_device(struct mtd_info *mtd)
mtd->cdev.priv = mtd;
mtd->cdev.dev = &mtd->class_dev;
- mtd->param_size.flags = PARAM_FLAG_RO;
- mtd->param_size.name = "size";
- mtd->param_size.value = asprintf("%u", mtd->size);
- dev_add_param(&mtd->class_dev, &mtd->param_size);
+ sprintf(str, "%u", mtd->size);
+ dev_add_param_fixed(&mtd->class_dev, "size", str);
devfs_create(&mtd->cdev);
diff --git a/drivers/net/at91_ether.c b/drivers/net/at91_ether.c
index a2d15948f3..3c4f4b053c 100644
--- a/drivers/net/at91_ether.c
+++ b/drivers/net/at91_ether.c
@@ -190,7 +190,7 @@ static int at91rm9200_eth_rx (struct eth_device *edev)
return 0;
size = rbfp->size & RBF_SIZE;
- NetReceive ((volatile uchar *) (rbfp->addr & RBF_ADDR), size);
+ net_receive((volatile uchar *) (rbfp->addr & RBF_ADDR), size);
rbfp->addr &= ~RBF_OWNER;
if (rbfp->addr & RBF_WRAP)
diff --git a/drivers/net/cs8900.c b/drivers/net/cs8900.c
index 64366acb15..8120877680 100644
--- a/drivers/net/cs8900.c
+++ b/drivers/net/cs8900.c
@@ -309,7 +309,7 @@ static int cs8900_recv(struct eth_device *dev)
if (len & 1) {
*addr++ = readw(priv->regs + CS8900_RTDATA0);
}
- NetReceive(NetRxPackets[0], len);
+ net_receive(NetRxPackets[0], len);
return len;
}
diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c
index 77c771bf32..2062c6669c 100644
--- a/drivers/net/dm9000.c
+++ b/drivers/net/dm9000.c
@@ -416,7 +416,7 @@ static int dm9000_eth_rx (struct eth_device *edev)
/* Pass to upper layer */
debug("passing packet to upper layer\n");
- NetReceive(NetRxPackets[0], RxLen);
+ net_receive(NetRxPackets[0], RxLen);
return RxLen;
}
return 0;
diff --git a/drivers/net/ep93xx.c b/drivers/net/ep93xx.c
index e91a92ef44..c6c46710d3 100644
--- a/drivers/net/ep93xx.c
+++ b/drivers/net/ep93xx.c
@@ -335,9 +335,9 @@ static int ep93xx_eth_rcv_packet(struct eth_device *edev)
* protocol stack. We track the total number of
* bytes in the frame (nbytes_frame) which will be
* used when we pass the data off to the protocol
- * layer via NetReceive().
+ * layer via net_receive().
*/
- NetReceive((uchar *)priv->rx_dq.current->word1,
+ net_receive((uchar *)priv->rx_dq.current->word1,
RX_STATUS_FRAME_LEN(priv->rx_sq.current));
pr_debug("reporting %d bytes...\n",
RX_STATUS_FRAME_LEN(priv->rx_sq.current));
diff --git a/drivers/net/fec_imx.c b/drivers/net/fec_imx.c
index 5e8e5ca197..40a7543706 100644
--- a/drivers/net/fec_imx.c
+++ b/drivers/net/fec_imx.c
@@ -515,7 +515,7 @@ static int fec_recv(struct eth_device *dev)
*/
frame = phys_to_virt(readl(&rbd->data_pointer));
frame_length = readw(&rbd->data_length) - 4;
- NetReceive(frame->data, frame_length);
+ net_receive(frame->data, frame_length);
len = frame_length;
} else {
if (bd_status & FEC_RBD_ERR) {
diff --git a/drivers/net/fec_mpc5200.c b/drivers/net/fec_mpc5200.c
index d803ddf603..ce9a21d15e 100644
--- a/drivers/net/fec_mpc5200.c
+++ b/drivers/net/fec_mpc5200.c
@@ -645,7 +645,7 @@ static int mpc5xxx_fec_recv(struct eth_device *dev)
*/
memcpy(buff, frame->head, 14);
memcpy(buff + 14, frame->data, frame_length);
- NetReceive(buff, frame_length);
+ net_receive(buff, frame_length);
len = frame_length;
}
/*
diff --git a/drivers/net/macb.c b/drivers/net/macb.c
index 1bb833ae69..4feeed0ba1 100644
--- a/drivers/net/macb.c
+++ b/drivers/net/macb.c
@@ -190,7 +190,7 @@ static int macb_recv(struct eth_device *edev)
buffer = (void *)NetRxPackets[0];
}
- NetReceive(buffer, length);
+ net_receive(buffer, length);
if (++rx_tail >= CFG_MACB_RX_RING_SIZE)
rx_tail = 0;
reclaim_rx_buffers(macb, rx_tail);
diff --git a/drivers/net/netx_eth.c b/drivers/net/netx_eth.c
index 673007aca1..f2d7b4ae8a 100644
--- a/drivers/net/netx_eth.c
+++ b/drivers/net/netx_eth.c
@@ -111,7 +111,7 @@ static int netx_eth_rx (struct eth_device *edev)
/* get data */
memcpy((void*)NetRxPackets[0], (void *)(SRAM_BASE(seg) + frameno * 1560), len);
/* pass to barebox */
- NetReceive(NetRxPackets[0], len);
+ net_receive(NetRxPackets[0], len);
PFIFO_REG(PFIFO_BASE(EMPTY_PTR_FIFO(xcno))) =
FIFO_PTR_SEGMENT(seg) |
diff --git a/drivers/net/smc91111.c b/drivers/net/smc91111.c
index 9b41c67258..58ebaa9b18 100644
--- a/drivers/net/smc91111.c
+++ b/drivers/net/smc91111.c
@@ -1156,7 +1156,7 @@ static int smc91c111_eth_rx(struct eth_device *edev)
if (!is_error) {
/* Pass the packet up to the protocol layers. */
- NetReceive(NetRxPackets[0], packet_length);
+ net_receive(NetRxPackets[0], packet_length);
return packet_length;
}
diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c
index 4a5e7b614c..ca320d5a90 100644
--- a/drivers/net/smc911x.c
+++ b/drivers/net/smc911x.c
@@ -668,7 +668,7 @@ static int smc911x_eth_rx(struct eth_device *edev)
": dropped bad packet. Status: 0x%08x\n",
status);
else
- NetReceive(NetRxPackets[0], pktlen);
+ net_receive(NetRxPackets[0], pktlen);
}
return 0;
diff --git a/drivers/net/tap.c b/drivers/net/tap.c
index 8673436caf..522a9f11f0 100644
--- a/drivers/net/tap.c
+++ b/drivers/net/tap.c
@@ -48,7 +48,7 @@ int tap_eth_rx (struct eth_device *edev)
length = linux_read_nonblock(priv->fd, NetRxPackets[0], PKTSIZE);
if (length > 0)
- NetReceive(NetRxPackets[0], length);
+ net_receive(NetRxPackets[0], length);
return 0;
}
diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c
index e44ce67b6e..fc4146fdbc 100644
--- a/drivers/net/usb/asix.c
+++ b/drivers/net/usb/asix.c
@@ -425,7 +425,7 @@ static int asix_rx_fixup(struct usbnet *dev, void *buf, int len)
return 0;
}
- NetReceive(buf, size);
+ net_receive(buf, size);
buf += ((size + 1) & 0xfffe);
len -= ((size + 1) & 0xfffe);
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index 123cc3b30c..b0e309096a 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -137,7 +137,7 @@ static int usbnet_recv(struct eth_device *edev)
if (info->rx_fixup)
return info->rx_fixup(dev, rx_buf, alen);
else
- NetReceive(rx_buf, alen);
+ net_receive(rx_buf, alen);
}
return 0;
diff --git a/drivers/video/fb.c b/drivers/video/fb.c
index 00a0f6a177..841c3afe9e 100644
--- a/drivers/video/fb.c
+++ b/drivers/video/fb.c
@@ -32,15 +32,22 @@ static int fb_enable_set(struct device_d *dev, struct param_d *param,
{
struct fb_info *info = dev->priv;
int enable;
+ char *new;
+
+ if (!val)
+ return dev_param_set_generic(dev, param, NULL);
enable = simple_strtoul(val, NULL, 0);
- if (enable)
+ if (enable) {
info->fbops->fb_enable(info);
- else
+ new = "1";
+ } else {
info->fbops->fb_disable(info);
+ new = "0";
+ }
- sprintf(info->enable_string, "%d", !!enable);
+ dev_param_set_generic(dev, param, new);
return 0;
}
@@ -71,13 +78,9 @@ int register_framebuffer(struct fb_info *info)
sprintf(dev->name, "fb");
- info->param_enable.set = fb_enable_set;
- info->param_enable.name = "enable";
- sprintf(info->enable_string, "%d", 0);
- info->param_enable.value = info->enable_string;
- dev_add_param(dev, &info->param_enable);
-
register_device(&info->dev);
+ dev_add_param(dev, "enable", fb_enable_set, NULL, 0);
+ dev_set_param(dev, "enable", "0");
devfs_create(&info->cdev);
diff --git a/drivers/video/imx.c b/drivers/video/imx.c
index 67cae349e5..d9ba643acb 100644
--- a/drivers/video/imx.c
+++ b/drivers/video/imx.c
@@ -154,8 +154,6 @@ struct imxfb_info {
struct fb_info overlay;
- struct param_d param_alpha;
- char alpha_string[4];
};
#define IMX_NAME "IMX"
@@ -427,8 +425,12 @@ static int imxfb_alpha_set(struct device_d *dev, struct param_d *param,
struct fb_info *overlay = dev->priv;
struct imxfb_info *fbi = overlay->priv;
int alpha;
+ char alphastr[16];
unsigned int tmp;
+ if (!val)
+ return dev_param_set_generic(dev, param, NULL);
+
alpha = simple_strtoul(val, NULL, 0);
alpha &= 0xff;
@@ -437,7 +439,9 @@ static int imxfb_alpha_set(struct device_d *dev, struct param_d *param,
tmp |= LGWCR_GWAV(alpha);
writel(tmp , fbi->regs + LCDC_LGWCR);
- sprintf(fbi->alpha_string, "%d", alpha);
+ sprintf(alphastr, "%d", alpha);
+
+ dev_param_set_generic(dev, param, alphastr);
return 0;
}
@@ -502,11 +506,8 @@ static int imxfb_register_overlay(struct imxfb_info *fbi, void *fb)
return ret;
}
- fbi->param_alpha.set = imxfb_alpha_set;
- fbi->param_alpha.name = "alpha";
- sprintf(fbi->alpha_string, "%d", 0);
- fbi->param_alpha.value = fbi->alpha_string;
- dev_add_param(&overlay->dev, &fbi->param_alpha);
+ dev_add_param(&overlay->dev, "alpha", imxfb_alpha_set, NULL, 0);
+ dev_set_param(&overlay->dev, "alpha", "0");
return 0;
}
diff --git a/include/console.h b/include/console.h
index 3568c562a8..3bcc5dbbc0 100644
--- a/include/console.h
+++ b/include/console.h
@@ -46,12 +46,6 @@ struct console_device {
unsigned char f_caps;
unsigned char f_active;
-
- struct param_d baudrate_param;
- char baudrate_string[8];
-
- struct param_d active_param;
- char active[4];
};
int console_register(struct console_device *cdev);
diff --git a/include/driver.h b/include/driver.h
index 1dde38e021..6950c02047 100644
--- a/include/driver.h
+++ b/include/driver.h
@@ -98,7 +98,7 @@ struct device_d {
/*! The parameters for this device. This is used to carry information
* of board specific data from the board code to the device driver. */
- struct param_d *param;
+ struct list_head parameters;
struct list_head cdevs;
};
diff --git a/include/fb.h b/include/fb.h
index f213c420d4..218500b985 100644
--- a/include/fb.h
+++ b/include/fb.h
@@ -80,8 +80,6 @@ struct fb_info {
struct fb_ops *fbops;
struct device_d dev; /* This is this fb device */
- struct param_d param_enable;
- char enable_string[1];
void *screen_base;
diff --git a/include/net.h b/include/net.h
index 7353c8f501..8db83d8309 100644
--- a/include/net.h
+++ b/include/net.h
@@ -15,48 +15,19 @@
#include <driver.h>
#include <linux/types.h>
#include <param.h>
+#include <malloc.h>
#include <asm/byteorder.h> /* for nton* / ntoh* stuff */
-/*
- * The number of receive packet buffers, and the required packet buffer
- * alignment in memory.
- *
- */
-
-#ifdef CFG_RX_ETH_BUFFER
-# define PKTBUFSRX CFG_RX_ETH_BUFFER
-#else
-# define PKTBUFSRX 4
-#endif
-
-#define PKTALIGN 32
-
-/*
- * The current receive packet handler. Called with a pointer to the
- * application packet, and a protocol type (PORT_BOOTPC or PORT_TFTP).
- * All other packets are dealt with without calling the handler.
- */
-typedef void rxhand_f(uchar *, unsigned, unsigned, unsigned);
-
-/*
- * A timeout handler. Called after time interval has expired.
- */
-typedef void thand_f(void);
-
-#define NAMESIZE 16
-
-enum eth_state_t {
- ETH_STATE_INIT,
- ETH_STATE_PASSIVE,
- ETH_STATE_ACTIVE
-};
+/* The number of receive packet buffers */
+#define PKTBUFSRX 4
struct device_d;
struct eth_device {
int iobase;
int state;
+ int active;
int (*init) (struct eth_device*);
@@ -70,12 +41,6 @@ struct eth_device {
struct eth_device *next;
void *priv;
- struct param_d param_ip;
- struct param_d param_netmask;
- struct param_d param_gateway;
- struct param_d param_serverip;
- struct param_d param_ethaddr;
-
struct device_d dev;
struct list_head list;
@@ -90,43 +55,16 @@ int eth_rx(void); /* Check for received packets */
void eth_halt(void); /* stop SCC */
char *eth_get_name(void); /* get name of current device */
-
-/**********************************************************************/
-/*
- * Protocol headers.
- */
-
/*
* Ethernet header
*/
-typedef struct {
- uchar et_dest[6]; /* Destination node */
- uchar et_src[6]; /* Source node */
- ushort et_protlen; /* Protocol or length */
- uchar et_dsap; /* 802 DSAP */
- uchar et_ssap; /* 802 SSAP */
- uchar et_ctl; /* 802 control */
- uchar et_snap1; /* SNAP */
- uchar et_snap2;
- uchar et_snap3;
- ushort et_prot; /* 802 protocol */
-} Ethernet_t;
+struct ethernet {
+ uint8_t et_dest[6]; /* Destination node */
+ uint8_t et_src[6]; /* Source node */
+ uint16_t et_protlen; /* Protocol or length */
+} __attribute__ ((packed));
#define ETHER_HDR_SIZE 14 /* Ethernet header size */
-#define E802_HDR_SIZE 22 /* 802 ethernet header size */
-
-/*
- * Ethernet header
- */
-typedef struct {
- uchar vet_dest[6]; /* Destination node */
- uchar vet_src[6]; /* Source node */
- ushort vet_vlan_type; /* PROT_VLAN */
- ushort vet_tag; /* TAG of VLAN */
- ushort vet_type; /* protocol type */
-} VLAN_Ethernet_t;
-
-#define VLAN_ETHER_HDR_SIZE 18 /* VLAN Ethernet header size */
#define PROT_IP 0x0800 /* IP protocol */
#define PROT_ARP 0x0806 /* IP ARP protocol */
@@ -139,53 +77,53 @@ typedef struct {
/*
* Internet Protocol (IP) header.
*/
-typedef struct {
- uchar ip_hl_v; /* header length and version */
- uchar ip_tos; /* type of service */
- ushort ip_len; /* total length */
- ushort ip_id; /* identification */
- ushort ip_off; /* fragment offset field */
- uchar ip_ttl; /* time to live */
- uchar ip_p; /* protocol */
- ushort ip_sum; /* checksum */
- IPaddr_t ip_src; /* Source IP address */
- IPaddr_t ip_dst; /* Destination IP address */
- ushort udp_src; /* UDP source port */
- ushort udp_dst; /* UDP destination port */
- ushort udp_len; /* Length of UDP packet */
- ushort udp_xsum; /* Checksum */
-} IP_t;
-
-#define IP_HDR_SIZE_NO_UDP (sizeof (IP_t) - 8)
-#define IP_HDR_SIZE (sizeof (IP_t))
-
+struct iphdr {
+ uint8_t hl_v;
+ uint8_t tos;
+ uint16_t tot_len;
+ uint16_t id;
+ uint16_t frag_off;
+ uint8_t ttl;
+ uint8_t protocol;
+ uint16_t check;
+ uint32_t saddr;
+ uint32_t daddr;
+ /* The options start here. */
+} __attribute__ ((packed));
+
+struct udphdr {
+ uint16_t uh_sport; /* source port */
+ uint16_t uh_dport; /* destination port */
+ uint16_t uh_ulen; /* udp length */
+ uint16_t uh_sum; /* udp checksum */
+} __attribute__ ((packed));
/*
* Address Resolution Protocol (ARP) header.
*/
-typedef struct
+struct arprequest
{
- ushort ar_hrd; /* Format of hardware address */
-# define ARP_ETHER 1 /* Ethernet hardware address */
- ushort ar_pro; /* Format of protocol address */
- uchar ar_hln; /* Length of hardware address */
- uchar ar_pln; /* Length of protocol address */
- ushort ar_op; /* Operation */
-# define ARPOP_REQUEST 1 /* Request to resolve address */
-# define ARPOP_REPLY 2 /* Response to previous request */
-
-# define RARPOP_REQUEST 3 /* Request to resolve address */
-# define RARPOP_REPLY 4 /* Response to previous request */
+ uint16_t ar_hrd; /* Format of hardware address */
+#define ARP_ETHER 1 /* Ethernet hardware address */
+ uint16_t ar_pro; /* Format of protocol address */
+ uint8_t ar_hln; /* Length of hardware address */
+ uint8_t ar_pln; /* Length of protocol address */
+ uint16_t ar_op; /* Operation */
+#define ARPOP_REQUEST 1 /* Request to resolve address */
+#define ARPOP_REPLY 2 /* Response to previous request */
+
+#define RARPOP_REQUEST 3 /* Request to resolve address */
+#define RARPOP_REPLY 4 /* Response to previous request */
/*
* The remaining fields are variable in size, according to
* the sizes above, and are defined as appropriate for
* specific hardware/protocol combinations.
*/
- uchar ar_data[0];
-} ARP_t;
+ uint8_t ar_data[0];
+} __attribute__ ((packed));
-#define ARP_HDR_SIZE (8+20) /* Size assuming ethernet */
+#define ARP_HDR_SIZE (8 + 20) /* Size assuming ethernet */
/*
* ICMP stuff (just enough to handle (host) redirect messages)
@@ -198,22 +136,22 @@ typedef struct
#define ICMP_REDIR_NET 0 /* Redirect Net */
#define ICMP_REDIR_HOST 1 /* Redirect Host */
-typedef struct icmphdr {
- uchar type;
- uchar code;
- ushort checksum;
+struct icmphdr {
+ uint8_t type;
+ uint8_t code;
+ uint16_t checksum;
union {
struct {
- ushort id;
- ushort sequence;
+ uint16_t id;
+ uint16_t sequence;
} echo;
- ulong gateway;
+ uint32_t gateway;
struct {
- ushort __unused;
- ushort mtu;
+ uint16_t __unused;
+ uint16_t mtu;
} frag;
} un;
-} ICMP_t;
+} __attribute__ ((packed));
/*
@@ -222,24 +160,7 @@ typedef struct icmphdr {
* Lets be conservative, and go for 38 * 16. (Must also be
* a multiple of 32 bytes).
*/
-/*
- * AS.HARNOIS : Better to set PKTSIZE to maximum size because
- * traffic type is not always controlled
- * maximum packet size = 1518
- * maximum packet size and multiple of 32 bytes = 1536
- */
#define PKTSIZE 1518
-#define PKTSIZE_ALIGN 1536
-/*#define PKTSIZE 608*/
-
-/*
- * Maximum receive ring size; that is, the number of packets
- * we can buffer before overflow happens. Basically, this just
- * needs to be enough to prevent a packet being discarded while
- * we are processing the previous one.
- */
-#define RINGSZ 4
-#define RINGSZ_LOG2 2
/**********************************************************************/
/*
@@ -251,98 +172,54 @@ typedef struct icmphdr {
* (big endian).
*/
-/* net.c */
-/** BOOTP EXTENTIONS **/
-extern IPaddr_t NetOurGatewayIP; /* Our gateway IP addresse */
-extern IPaddr_t NetOurSubnetMask; /* Our subnet mask (0 = unknown)*/
-extern IPaddr_t NetOurDNSIP; /* Our Domain Name Server (0 = unknown)*/
-extern IPaddr_t NetOurDNS2IP; /* Our 2nd Domain Name Server (0 = unknown)*/
-extern char NetOurNISDomain[32]; /* Our NIS domain */
-extern char NetOurHostName[32]; /* Our hostname */
-extern char NetOurRootPath[64]; /* Our root path */
-/** END OF BOOTP EXTENTIONS **/
-extern ulong NetBootFileXferSize; /* size of bootfile in bytes */
-extern uchar NetOurEther[6]; /* Our ethernet address */
-extern uchar NetServerEther[6]; /* Boot server enet address */
-extern IPaddr_t NetOurIP; /* Our IP addr (0 = unknown) */
-extern IPaddr_t NetServerIP; /* Server IP addr (0 = unknown) */
-extern uchar * NetTxPacket; /* THE transmit packet */
-extern uchar * NetRxPackets[PKTBUFSRX];/* Receive packets */
-extern 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 */
-extern ushort NetOurVLAN; /* Our VLAN */
-extern ushort NetOurNativeVLAN; /* Our Native VLAN */
-
-extern int NetState; /* Network loop state */
-
-/* ---------- Added by sha ------------ */
-extern IPaddr_t NetArpWaitPacketIP;
-extern uchar *NetArpWaitPacketMAC;
-extern uchar *NetArpWaitTxPacket; /* THE transmit packet */
-extern int NetArpWaitTxPacketSize;
-extern int NetArpWaitTry;
-extern uint64_t NetArpWaitTimerStart;
-extern void ArpRequest (void);
-/* ------------------------------------ */
-
-#define NETLOOP_CONTINUE 1
-#define NETLOOP_SUCCESS 2
-#define NETLOOP_FAIL 3
-
-typedef enum { BOOTP, RARP, ARP, TFTP, DHCP, PING, DNS, NFS, CDP, NETCONS, SNTP } proto_t;
-
-/* Initialize the network adapter */
-int NetLoopInit(proto_t);
+extern unsigned char *NetRxPackets[PKTBUFSRX];/* Receive packets */
-/* Do the work */
-int NetLoop(void);
+void net_set_ip(IPaddr_t ip);
+void net_set_serverip(IPaddr_t ip);
+void net_set_netmask(IPaddr_t ip);
+void net_set_gateway(IPaddr_t ip);
+IPaddr_t net_get_ip(void);
+IPaddr_t net_get_serverip(void);
-/* Shutdown adapters and cleanup */
-void NetStop(void);
-
-/* Load failed. Start again. */
-void NetStartAgain(void);
-
-/* Get size of the ethernet header when we send */
-int NetEthHdrSize(void);
+/* Do the work */
+void net_poll(void);
-/* Set ethernet header; returns the size of the header */
-int NetSetEther(uchar *, uchar *, uint);
+static inline struct iphdr *net_eth_to_iphdr(char *pkt)
+{
+ return (struct iphdr *)(pkt + ETHER_HDR_SIZE);
+}
-/* Set IP header */
-void NetSetIP(uchar *, IPaddr_t, int, int, int);
+static inline struct udphdr *net_eth_to_udphdr(char *pkt)
+{
+ return (struct udphdr *)(net_eth_to_iphdr(pkt) + 1);
+}
-/* Checksum */
-int NetCksumOk(uchar *, int); /* Return true if cksum OK */
-uint NetCksum(uchar *, int); /* Calculate the checksum */
+static inline struct icmphdr *net_eth_to_icmphdr(char *pkt)
+{
+ return (struct icmphdr *)(net_eth_to_iphdr(pkt) + 1);
+}
-/* Set callbacks */
-void NetSetHandler(rxhand_f *); /* Set RX packet handler */
-void NetSetTimeout(uint64_t, thand_f *);/* Set timeout handler */
+static inline char *net_eth_to_icmp_payload(char *pkt)
+{
+ return (char *)(net_eth_to_icmphdr(pkt) + 1);
+}
-/* Transmit "NetTxPacket" */
-void NetSendPacket(uchar *, int);
+static inline char *net_eth_to_udp_payload(char *pkt)
+{
+ return (char *)(net_eth_to_udphdr(pkt) + 1);
+}
-/* Transmit UDP packet, performing ARP request if needed */
-int NetSendUDPPacket(uchar *ether, IPaddr_t dest, int dport, int sport, int len);
+static inline int net_eth_to_udplen(char *pkt)
+{
+ struct udphdr *udp = net_eth_to_udphdr(pkt);
+ return ntohs(udp->uh_ulen) - 8;
+}
-/* Processes a received packet */
-void NetReceive(uchar *, int);
+int net_checksum_ok(unsigned char *, int); /* Return true if cksum OK */
+uint16_t net_checksum(unsigned char *, int); /* Calculate the checksum */
/* Print an IP address on the console */
-#ifdef CONFIG_NET
-void print_IPaddr (IPaddr_t);
-#else
-#define print_IPaddr(IPaddr_t);
-#endif
-
-void netboot_update_env(void);
+void print_IPaddr (IPaddr_t);
/*
* The following functions are a bit ugly, but necessary to deal with
@@ -352,15 +229,15 @@ void netboot_update_env(void);
* footprint in our tests.
*/
/* return IP *in network byteorder* */
-static inline IPaddr_t NetReadIP(void *from)
+static inline IPaddr_t net_read_ip(void *from)
{
IPaddr_t ip;
memcpy((void*)&ip, from, sizeof(ip));
return ip;
}
-/* return ulong *in network byteorder* */
-static inline ulong NetReadLong(ulong *from)
+/* return uint32 *in network byteorder* */
+static inline uint32_t net_read_uint32(uint32_t *from)
{
ulong l;
memcpy((void*)&l, (void*)from, sizeof(l));
@@ -368,50 +245,159 @@ static inline ulong NetReadLong(ulong *from)
}
/* write IP *in network byteorder* */
-static inline void NetWriteIP(void *to, IPaddr_t ip)
+static inline void net_write_ip(void *to, IPaddr_t ip)
{
memcpy(to, (void*)&ip, sizeof(ip));
}
/* copy IP */
-static inline void NetCopyIP(void *to, void *from)
+static inline void net_copy_ip(void *to, void *from)
{
memcpy(to, from, sizeof(IPaddr_t));
}
/* copy ulong */
-static inline void NetCopyLong(ulong *to, ulong *from)
+static inline void net_copy_uint32(uint32_t *to, uint32_t *from)
{
- memcpy((void*)to, (void*)from, sizeof(ulong));
+ memcpy(to, from, sizeof(uint32_t));
}
/* Convert an IP address to a string */
-char * ip_to_string (IPaddr_t x, char *s);
+char *ip_to_string (IPaddr_t x, char *s);
/* Convert a string to ip address */
int string_to_ip(const char *s, IPaddr_t *ip);
-/* Convert a VLAN id to a string */
-void VLAN_to_string (ushort x, char *s);
+IPaddr_t getenv_ip(const char *name);
+int setenv_ip(const char *name, IPaddr_t ip);
-/* Convert a string to a vlan id */
-ushort string_to_VLAN(const char *s);
+int string_to_ethaddr(const char *str, char *enetaddr);
+void ethaddr_to_string(const unsigned char *enetaddr, char *str);
-/* read an IP address from a environment variable */
-IPaddr_t getenv_IPaddr (char *);
+#ifdef CONFIG_NET_RESOLV
+IPaddr_t resolv(char *host);
+#else
+static inline IPaddr_t resolv(char *host)
+{
+ IPaddr_t ip = 0;
+ string_to_ip(host, &ip);
+ return ip;
+}
+#endif
-/* read a VLAN id from an environment variable */
-ushort getenv_VLAN(char *);
+/**
+ * is_zero_ether_addr - Determine if give Ethernet address is all zeros.
+ * @addr: Pointer to a six-byte array containing the Ethernet address
+ *
+ * Return true if the address is all zeroes.
+ */
+static inline int is_zero_ether_addr(const u8 *addr)
+{
+ return !(addr[0] | addr[1] | addr[2] | addr[3] | addr[4] | addr[5]);
+}
-int string_to_ethaddr(const char *str, char *enetaddr);
-void ethaddr_to_string(const unsigned char *enetaddr, char *str);
+/**
+ * is_multicast_ether_addr - Determine if the Ethernet address is a multicast.
+ * @addr: Pointer to a six-byte array containing the Ethernet address
+ *
+ * Return true if the address is a multicast address.
+ * By definition the broadcast address is also a multicast address.
+ */
+static inline int is_multicast_ether_addr(const u8 *addr)
+{
+ return (0x01 & addr[0]);
+}
-/**********************************************************************/
-/* Network devices */
-/**********************************************************************/
+/**
+ * is_local_ether_addr - Determine if the Ethernet address is locally-assigned one (IEEE 802).
+ * @addr: Pointer to a six-byte array containing the Ethernet address
+ *
+ * Return true if the address is a local address.
+ */
+static inline int is_local_ether_addr(const u8 *addr)
+{
+ return (0x02 & addr[0]);
+}
+
+/**
+ * is_broadcast_ether_addr - Determine if the Ethernet address is broadcast
+ * @addr: Pointer to a six-byte array containing the Ethernet address
+ *
+ * Return true if the address is the broadcast address.
+ */
+static inline int is_broadcast_ether_addr(const u8 *addr)
+{
+ return (addr[0] & addr[1] & addr[2] & addr[3] & addr[4] & addr[5]) == 0xff;
+}
+
+/**
+ * is_valid_ether_addr - Determine if the given Ethernet address is valid
+ * @addr: Pointer to a six-byte array containing the Ethernet address
+ *
+ * Check that the Ethernet address (MAC) is not 00:00:00:00:00:00, is not
+ * a multicast address, and is not FF:FF:FF:FF:FF:FF.
+ *
+ * Return true if the address is valid.
+ */
+static inline int is_valid_ether_addr(const u8 *addr)
+{
+ /* FF:FF:FF:FF:FF:FF is a multicast address so we don't need to
+ * explicitly check for it here. */
+ return !is_multicast_ether_addr(addr) && !is_zero_ether_addr(addr);
+}
+
+typedef void rx_handler_f(char *packet, unsigned int len);
void eth_set_current(struct eth_device *eth);
struct eth_device *eth_get_current(void);
struct eth_device *eth_get_byname(char *name);
+void net_update_env(void);
+
+/**
+ * net_receive - Pass a received packet from an ethernet driver to the protocol stack
+ * @pkt: Pointer to the packet
+ * @len: length of the packet
+ *
+ * Return 0 if the packet is successfully handled. Can be ignored
+ */
+int net_receive(unsigned char *pkt, int len);
+
+struct net_connection {
+ struct ethernet *et;
+ struct iphdr *ip;
+ struct udphdr *udp;
+ struct icmphdr *icmp;
+ unsigned char *packet;
+ struct list_head list;
+ rx_handler_f *handler;
+ int proto;
+};
+
+static inline char *net_alloc_packet(void)
+{
+ return memalign(32, PKTSIZE);
+}
+
+struct net_connection *net_udp_new(IPaddr_t dest, uint16_t dport,
+ rx_handler_f *handler);
+
+struct net_connection *net_icmp_new(IPaddr_t dest, rx_handler_f *handler);
+
+void net_unregister(struct net_connection *con);
+
+static inline int net_udp_bind(struct net_connection *con, int sport)
+{
+ con->udp->uh_sport = ntohs(sport);
+ return 0;
+}
+
+static inline unsigned char *net_udp_get_payload(struct net_connection *con)
+{
+ return con->packet + sizeof(struct ethernet) + sizeof(struct iphdr) +
+ sizeof(struct udphdr);
+}
+
+int net_udp_send(struct net_connection *con, int len);
+int net_icmp_send(struct net_connection *con, int len);
#endif /* __NET_H__ */
diff --git a/include/param.h b/include/param.h
index fe4468ed2c..207ad5016a 100644
--- a/include/param.h
+++ b/include/param.h
@@ -2,6 +2,7 @@
#define PARAM_H
#include <linux/types.h>
+#include <linux/list.h>
#define PARAM_FLAG_RO (1 << 0)
@@ -15,12 +16,24 @@ struct param_d {
char *name;
struct param_d *next;
char *value;
+ struct list_head list;
};
const char *dev_get_param(struct device_d *dev, const char *name);
int dev_set_param(struct device_d *dev, const char *name, const char *val);
struct param_d *get_param_by_name(struct device_d *dev, const char *name);
-int dev_add_param(struct device_d *dev, struct param_d *par);
+
+int dev_add_param(struct device_d *dev, char *name,
+ int (*set)(struct device_d *dev, struct param_d *p, const char *val),
+ char *(*get)(struct device_d *, struct param_d *p),
+ unsigned long flags);
+
+int dev_add_param_fixed(struct device_d *dev, char *name, char *value);
+
+void dev_remove_parameters(struct device_d *dev);
+
+int dev_param_set_generic(struct device_d *dev, struct param_d *p,
+ const char *val);
/* Convenience functions to handle a parameter as an ip address */
int dev_set_param_ip(struct device_d *dev, char *name, IPaddr_t ip);
diff --git a/lib/driver.c b/lib/driver.c
index f433c3e9bf..b60074511f 100644
--- a/lib/driver.c
+++ b/lib/driver.c
@@ -107,6 +107,7 @@ int register_device(struct device_d *new_device)
list_add_tail(&new_device->list, &device_list);
INIT_LIST_HEAD(&new_device->children);
INIT_LIST_HEAD(&new_device->cdevs);
+ INIT_LIST_HEAD(&new_device->parameters);
for_each_driver(drv) {
if (!match(drv, new_device))
@@ -313,16 +314,11 @@ static int do_devinfo(struct command *cmdtp, int argc, char *argv[])
if (dev->driver)
dev->driver->info(dev);
- param = dev->param;
+ printf("%s\n", list_empty(&dev->parameters) ?
+ "no parameters available" : "Parameters:");
- printf("%s\n", param ?
- "Parameters:" : "no parameters available");
-
- while (param) {
+ list_for_each_entry(param, &dev->parameters, list)
printf("%16s = %s\n", param->name, param->value);
- param = param->next;
- }
-
}
return 0;
diff --git a/lib/parameter.c b/lib/parameter.c
index 6b32207cd5..0aa4193431 100644
--- a/lib/parameter.c
+++ b/lib/parameter.c
@@ -33,17 +33,22 @@
struct param_d *get_param_by_name(struct device_d *dev, const char *name)
{
- struct param_d *param = dev->param;
+ struct param_d *p;
- while (param) {
- if (!strcmp(param->name, name))
- return param;
- param = param->next;
+ list_for_each_entry(p, &dev->parameters, list) {
+ if (!strcmp(p->name, name))
+ return p;
}
return NULL;
}
+/**
+ * dev_get_param - get the value of a parameter
+ * @param dev The device
+ * @param name The name of the parameter
+ * @return The value
+ */
const char *dev_get_param(struct device_d *dev, const char *name)
{
struct param_d *param = get_param_by_name(dev, name);
@@ -53,10 +58,7 @@ const char *dev_get_param(struct device_d *dev, const char *name)
return NULL;
}
- if (param->get)
- return param->get(dev, param);
-
- return param->value;
+ return param->get(dev, param);
}
#ifdef CONFIG_NET
@@ -80,6 +82,12 @@ int dev_set_param_ip(struct device_d *dev, char *name, IPaddr_t ip)
}
#endif
+/**
+ * dev_set_param - set a parameter of a device to a new value
+ * @param dev The device
+ * @param name The name of the parameter
+ * @param value The new value of the parameter
+ */
int dev_set_param(struct device_d *dev, const char *name, const char *val)
{
struct param_d *param;
@@ -101,35 +109,124 @@ int dev_set_param(struct device_d *dev, const char *name, const char *val)
return -EACCES;
}
- if (param->set) {
- errno = param->set(dev, param, val);
- return errno;
+ errno = param->set(dev, param, val);
+ return errno;
+}
+
+/**
+ * dev_param_set_generic - generic setter function for a parameter
+ * @param dev The device
+ * @param p the parameter
+ * @param val The new value
+ *
+ * If used the value of a parameter is a string allocated with
+ * malloc and freed with free. If val is NULL the value is freed. This is
+ * used during deregistration of the parameter to free the alloctated
+ * memory.
+ */
+int dev_param_set_generic(struct device_d *dev, struct param_d *p,
+ const char *val)
+{
+ if (p->value)
+ free(p->value);
+ if (!val) {
+ p->value = NULL;
+ return 0;
}
+ p->value = strdup(val);
+ return 0;
+}
- if (param->value)
- free(param->value);
+static char *param_get_generic(struct device_d *dev, struct param_d *p)
+{
+ return p->value;
+}
- param->value = strdup(val);
- return 0;
+static struct param_d *__dev_add_param(struct device_d *dev, char *name,
+ int (*set)(struct device_d *dev, struct param_d *p, const char *val),
+ char *(*get)(struct device_d *dev, struct param_d *p),
+ unsigned long flags)
+{
+ struct param_d *param;
+
+ param = xzalloc(sizeof(*param));
+
+ if (set)
+ param->set = set;
+ else
+ param->set = dev_param_set_generic;
+ if (get)
+ param->get = get;
+ else
+ param->get = param_get_generic;
+
+ param->name = strdup(name);
+ param->flags = flags;
+ list_add_tail(&param->list, &dev->parameters);
+
+ return param;
}
-int dev_add_param(struct device_d *dev, struct param_d *newparam)
+/**
+ * dev_add_param - add a parameter to a device
+ * @param dev The device
+ * @param name The name of the parameter
+ * @param set setter function for the parameter
+ * @param get getter function for the parameter
+ * @param flags
+ *
+ * This function adds a new parameter to a device. The get/set functions can
+ * be zero in which case the generic functions are used. The generic functions
+ * expect the parameter value to be a string which can be freed with free(). Do
+ * not use static arrays when using the generic functions.
+ */
+int dev_add_param(struct device_d *dev, char *name,
+ int (*set)(struct device_d *dev, struct param_d *p, const char *val),
+ char *(*get)(struct device_d *dev, struct param_d *param),
+ unsigned long flags)
{
- struct param_d *param = dev->param;
+ struct param_d *param;
- newparam->next = NULL;
+ param = __dev_add_param(dev, name, set, get, flags);
- if (param) {
- while (param->next)
- param = param->next;
- param->next = newparam;
- } else {
- dev->param = newparam;
- }
+ return param ? 0 : -EINVAL;
+}
+
+/**
+ * dev_add_param_fixed - add a readonly parameter to a device
+ * @param dev The device
+ * @param name The name of the parameter
+ * @param value The value of the parameter
+ */
+int dev_add_param_fixed(struct device_d *dev, char *name, char *value)
+{
+ struct param_d *param;
+
+ param = __dev_add_param(dev, name, NULL, NULL, PARAM_FLAG_RO);
+ if (!param)
+ return -EINVAL;
+
+ param->value = strdup(value);
return 0;
}
+/**
+ * dev_remove_parameters - remove all parameters from a device and free their
+ * memory
+ * @param dev The device
+ */
+void dev_remove_parameters(struct device_d *dev)
+{
+ struct param_d *p, *n;
+
+ list_for_each_entry_safe(p, n, &dev->parameters, list) {
+ p->set(dev, p, NULL);
+ list_del(&p->list);
+ free(p);
+ }
+}
+
/** @page dev_params Device parameters
@section params_devices Devices can have several parameters.
@@ -145,50 +242,6 @@ IP address of the first ethernet device is a matter of typing
devices currently present. If called with a device id as parameter it shows the
parameters available for a device.
-@section params_programming Device parameters programming API
-
-@code
-struct param_d {
- char* (*get)(struct device_d *, struct param_d *param);
- int (*set)(struct device_d *, struct param_d *param, const char *val);
- ulong flags;
- char *name;
- struct param_d *next;
- char *value;
-};
-@endcode
-
-@code
-int dev_add_param(struct device_d *dev, struct param_d *newparam);
-@endcode
-
-This function adds a new parameter to a device. At least the name field in
-the new parameter struct has to be initialized. The 'get' and 'set' fields
-can be set to NULL in which case the framework handles them. It is also
-allowed to implement only one of the get/set functions. Care must be taken
-with the initial value of the parameter. If the framework handles the set
-function it will try to free the value of the parameter. If this is a
-static array bad things will happen. A parameter can have the flag
-PARAM_FLAG_RO which means that the parameter is readonly. It is perfectly ok
-then to point the value to a static array.
-
-@code
-const char *dev_get_param(struct device_d *dev, const char *name);
-@endcode
-
-This function returns a pointer to the value of the parameter specified
-with dev and name.
-If the framework handles the get/set functions the parameter value strings
-are alloceted with malloc and freed with free when another value is set for
-this parameter. Drivers implementing set/get themselves are allowed to
-return values in static arrays. This means that the pointers returned from
-dev_get_param() are only valid until the next call to dev_get_param. If this
-is not long enough strdup() or similar must be used.
-
-@code
-int dev_set_param(struct device_d *dev, const char *name, const char *val);
-@endcode
-
-Set the value of a parameter.
+See the individual functions for parameter programming.
*/
diff --git a/net/Kconfig b/net/Kconfig
index cca2b00387..ff6e45523d 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -7,10 +7,6 @@ config NET_DHCP
bool
prompt "dhcp support"
-config NET_RARP
- bool
- prompt "rarp protocol support"
-
config NET_NFS
bool
prompt "nfs support"
@@ -22,4 +18,15 @@ config NET_PING
config NET_TFTP
bool
prompt "tftp support"
+
+config NET_NETCONSOLE
+ bool
+ prompt "network console support"
+ help
+ This option adds support for a simple udp based network console.
+
+config NET_RESOLV
+ bool
+ prompt "dns support"
+
endif
diff --git a/net/Makefile b/net/Makefile
index 0ffc8959c1..66dc564dac 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -2,6 +2,7 @@ obj-$(CONFIG_NET_DHCP) += dhcp.o
obj-$(CONFIG_NET) += eth.o
obj-$(CONFIG_NET) += net.o
obj-$(CONFIG_NET_NFS) += nfs.o
-obj-$(CONFIG_NET_RARP) += rarp.o
obj-$(CONFIG_NET_TFTP) += tftp.o
obj-$(CONFIG_NET_PING) += ping.o
+obj-$(CONFIG_NET_RESOLV)+= dns.o
+obj-$(CONFIG_NET_NETCONSOLE) += netconsole.o
diff --git a/net/dhcp.c b/net/dhcp.c
index f27a6966d7..0771964b91 100644
--- a/net/dhcp.c
+++ b/net/dhcp.c
@@ -14,64 +14,44 @@
#include <clock.h>
#include <net.h>
#include <libbb.h>
-#include "tftp.h"
-#include "nfs.h"
+#include <errno.h>
+#include <linux/err.h>
#define OPT_SIZE 312 /* Minimum DHCP Options size per RFC2131 - results in 576 byte pkt */
-typedef struct
-{
- uchar bp_op; /* Operation */
-# define OP_BOOTREQUEST 1
-# define OP_BOOTREPLY 2
- uchar bp_htype; /* Hardware type */
-# define HWT_ETHER 1
- uchar bp_hlen; /* Hardware address length */
-# define HWL_ETHER 6
- uchar bp_hops; /* Hop count (gateway thing) */
- ulong bp_id; /* Transaction ID */
- ushort bp_secs; /* Seconds since boot */
- ushort bp_spare1; /* Alignment */
+struct bootp {
+ uint8_t bp_op; /* Operation */
+#define OP_BOOTREQUEST 1
+#define OP_BOOTREPLY 2
+ uint8_t bp_htype; /* Hardware type */
+#define HWT_ETHER 1
+ uint8_t bp_hlen; /* Hardware address length */
+#define HWL_ETHER 6
+ uint8_t bp_hops; /* Hop count (gateway thing) */
+ uint32_t bp_id; /* Transaction ID */
+ uint16_t bp_secs; /* Seconds since boot */
+ uint16_t bp_spare1; /* Alignment */
IPaddr_t bp_ciaddr; /* Client IP address */
IPaddr_t bp_yiaddr; /* Your (client) IP address */
IPaddr_t bp_siaddr; /* Server IP address */
IPaddr_t bp_giaddr; /* Gateway IP address */
- uchar bp_chaddr[16]; /* Client hardware address */
+ uint8_t bp_chaddr[16]; /* Client hardware address */
char bp_sname[64]; /* Server host name */
char bp_file[128]; /* Boot file name */
- char bp_vend[OPT_SIZE]; /* Vendor information */
-} Bootp_t;
-
-#define BOOTP_HDR_SIZE sizeof (Bootp_t)
-#define BOOTP_SIZE (ETHER_HDR_SIZE + IP_HDR_SIZE + BOOTP_HDR_SIZE)
-
-/**********************************************************************/
-/*
- * Global functions and variables.
- */
-
-/* bootp.c */
-extern ulong BootpID; /* ID of cur BOOTP request */
-extern char BootFile[128]; /* Boot file name */
-#ifdef CONFIG_BOOTP_RANDOM_DELAY
-ulong seed1, seed2; /* seed for random BOOTP delay */
-#endif
-
-
-/* Send a BOOTP request */
-extern void BootpRequest (void);
-
-/****************** DHCP Support *********************/
+ char bp_vend[0]; /* Vendor information */
+};
/* DHCP States */
-typedef enum { INIT,
- INIT_REBOOT,
- REBOOTING,
- SELECTING,
- REQUESTING,
- REBINDING,
- BOUND,
- RENEWING } dhcp_state_t;
+typedef enum {
+ INIT,
+ INIT_REBOOT,
+ REBOOTING,
+ SELECTING,
+ REQUESTING,
+ REBINDING,
+ BOUND,
+ RENEWING,
+} dhcp_state_t;
#define DHCP_DISCOVER 1
#define DHCP_OFFER 2
@@ -81,44 +61,27 @@ typedef enum { INIT,
#define DHCP_NAK 6
#define DHCP_RELEASE 7
-#define SELECT_TIMEOUT 3 /* Seconds to wait for offers */
-
-/**********************************************************************/
-
#define BOOTP_VENDOR_MAGIC 0x63825363 /* RFC1048 Magic Cookie */
-#define TIMEOUT 5 /* Seconds before trying BOOTP again */
-#ifndef CONFIG_NET_RETRY_COUNT
-# define TIMEOUT_COUNT 5 /* # of timeouts before giving up */
-#else
-# define TIMEOUT_COUNT (CONFIG_NET_RETRY_COUNT)
-#endif
-
#define PORT_BOOTPS 67 /* BOOTP server UDP port */
#define PORT_BOOTPC 68 /* BOOTP client UDP port */
-#ifndef CONFIG_DHCP_MIN_EXT_LEN /* minimal length of extension list */
-#define CONFIG_DHCP_MIN_EXT_LEN 64
-#endif
-
-ulong BootpID;
-#ifdef CONFIG_BOOTP_RANDOM_DELAY
-ulong seed1, seed2;
-#endif
+#define DHCP_MIN_EXT_LEN 64 /* minimal length of extension list */
-dhcp_state_t dhcp_state = INIT;
-unsigned long dhcp_leasetime = 0;
-IPaddr_t NetDHCPServerIP = 0;
-static void DhcpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len);
+static uint32_t Bootp_id;
+static dhcp_state_t dhcp_state;
+static uint32_t dhcp_leasetime;
+static IPaddr_t net_dhcp_server_ip;
+static uint64_t dhcp_start;
-static int BootpCheckPkt(uchar *pkt, unsigned dest, unsigned src, unsigned len)
+static int bootp_check_packet(unsigned char *pkt, unsigned src, unsigned len)
{
- Bootp_t *bp = (Bootp_t *) pkt;
+ struct bootp *bp = (struct bootp *) pkt;
int retval = 0;
- if (dest != PORT_BOOTPC || src != PORT_BOOTPS)
+ if (src != PORT_BOOTPS)
retval = -1;
- else if (len < sizeof (Bootp_t) - OPT_SIZE)
+ else if (len < sizeof(struct bootp))
retval = -2;
else if (bp->bp_op != OP_BOOTREQUEST &&
bp->bp_op != OP_BOOTREPLY &&
@@ -131,11 +94,11 @@ static int BootpCheckPkt(uchar *pkt, unsigned dest, unsigned src, unsigned len)
retval = -4;
else if (bp->bp_hlen != HWL_ETHER)
retval = -5;
- else if (NetReadLong((ulong*)&bp->bp_id) != BootpID) {
+ else if (net_read_uint32(&bp->bp_id) != Bootp_id) {
retval = -6;
}
- debug ("Filtering pkt = %d\n", retval);
+ debug("Filtering pkt = %d\n", retval);
return retval;
}
@@ -143,64 +106,31 @@ static int BootpCheckPkt(uchar *pkt, unsigned dest, unsigned src, unsigned len)
/*
* Copy parameters of interest from BOOTP_REPLY/DHCP_OFFER packet
*/
-static void BootpCopyNetParams(Bootp_t *bp)
+static void bootp_copy_net_params(struct bootp *bp)
{
IPaddr_t tmp_ip;
- NetCopyIP(&NetOurIP, &bp->bp_yiaddr);
- NetCopyIP(&tmp_ip, &bp->bp_siaddr);
- if (tmp_ip != 0)
- NetCopyIP(&NetServerIP, &bp->bp_siaddr);
- memcpy (NetServerEther, ((Ethernet_t *)NetRxPkt)->et_src, 6);
- if (strlen(bp->bp_file) > 0)
- safe_strncpy (BootFile, bp->bp_file, sizeof(BootFile));
+ tmp_ip = net_read_ip(&bp->bp_yiaddr);
+ net_set_ip(tmp_ip);
- debug ("Bootfile: %s\n", BootFile);
-
- /* Propagate to environment:
- * don't delete exising entry when BOOTP / DHCP reply does
- * not contain a new value
- */
- if (*BootFile) {
- setenv ("bootfile", BootFile);
- }
-}
+ tmp_ip = net_read_ip(&bp->bp_siaddr);
+ if (tmp_ip != 0)
+ net_set_serverip(tmp_ip);
-static int truncate_sz (const char *name, int maxlen, int curlen)
-{
- if (curlen >= maxlen) {
- printf("*** WARNING: %s is too long (%d - max: %d) - truncated\n",
- name, curlen, maxlen);
- curlen = maxlen - 1;
- }
- return (curlen);
-}
+ if (strlen(bp->bp_file) > 0)
+ setenv("bootfile", bp->bp_file);
-/*
- * Timeout on BOOTP/DHCP request.
- */
-static void
-BootpTimeout(void)
-{
- NetSetTimeout (TIMEOUT * SECOND, BootpTimeout);
- BootpRequest ();
+ debug("bootfile: %s\n", bp->bp_file);
}
/*
- * Initialize BOOTP extension fields in the request.
+ * Initialize BOOTP extension fields in the request.
*/
-static int DhcpExtended (u8 * e, int message_type, IPaddr_t ServerID, IPaddr_t RequestedIP)
+static int dhcp_extended (u8 *e, int message_type, IPaddr_t ServerID, IPaddr_t RequestedIP)
{
u8 *start = e;
u8 *cnt;
-#ifdef CONFIG_BOOTP_VENDOREX
- u8 *x;
-#endif
-#ifdef CONFIG_BOOTP_SEND_HOSTNAME
- char *hostname;
-#endif
-
*e++ = 99; /* RFC1048 Magic Cookie */
*e++ = 130;
*e++ = 83;
@@ -236,175 +166,118 @@ static int DhcpExtended (u8 * e, int message_type, IPaddr_t ServerID, IPaddr_t R
*e++ = tmp >> 8;
*e++ = tmp & 0xff;
}
-#ifdef CONFIG_BOOTP_SEND_HOSTNAME
- if ((hostname = getenv ("hostname"))) {
- int hostnamelen = strlen (hostname);
-
- *e++ = 12; /* Hostname */
- *e++ = hostnamelen;
- memcpy (e, hostname, hostnamelen);
- e += hostnamelen;
- }
-#endif
*e++ = 55; /* Parameter Request List */
cnt = e++; /* Pointer to count of requested items */
*cnt = 0;
-#ifdef CONFIG_BOOTP_SUBNETMASK
*e++ = 1; /* Subnet Mask */
*cnt += 1;
-#endif
-#ifdef CONFIG_BOOTP_TIMEOFFSET
- *e++ = 2;
- *cnt += 1;
-#endif
-#ifdef CONFIG_BOOTP_GATEWAY
*e++ = 3; /* Router Option */
*cnt += 1;
-#endif
-#ifdef CONFIG_BOOTP_DNS
*e++ = 6; /* DNS Server(s) */
*cnt += 1;
-#endif
-#ifdef CONFIG_BOOTP_HOSTNAME
*e++ = 12; /* Hostname */
*cnt += 1;
-#endif
-#ifdef CONFIG_BOOTP_BOOTFILESIZE
- *e++ = 13; /* Boot File Size */
+ *e++ = 15; /* domain name */
*cnt += 1;
-#endif
-#ifdef CONFIG_BOOTP_BOOTPATH
*e++ = 17; /* Boot path */
*cnt += 1;
-#endif
-#ifdef CONFIG_BOOTP_NISDOMAIN
- *e++ = 40; /* NIS Domain name request */
- *cnt += 1;
-#endif
-#ifdef CONFIG_BOOTP_NTPSERVER
- *e++ = 42;
- *cnt += 1;
-#endif
*e++ = 255; /* End of the list */
/* Pad to minimal length */
-#ifdef CONFIG_DHCP_MIN_EXT_LEN
- while ((e - start) <= CONFIG_DHCP_MIN_EXT_LEN)
+ while ((e - start) <= DHCP_MIN_EXT_LEN)
*e++ = 0;
-#endif
return e - start;
}
-void
-BootpRequest (void)
+static struct net_connection *dhcp_con;
+
+static int bootp_request(void)
{
- uchar *pkt, *iphdr;
- Bootp_t *bp;
- int ext_len, pktlen, iplen;
+ struct bootp *bp;
+ int ext_len;
+ int ret;
+ unsigned char *payload = net_udp_get_payload(dhcp_con);
+ const char *bfile;
dhcp_state = INIT;
- printf("BOOTP broadcast\n");
- pkt = NetTxPacket;
- memset ((void*)pkt, 0, PKTSIZE);
+ debug("BOOTP broadcast\n");
- pkt += NetSetEther(pkt, NetBcastAddr, PROT_IP);
-
- /*
- * Next line results in incorrect packet size being transmitted, resulting
- * in errors in some DHCP servers, reporting missing bytes. Size must be
- * set in packet header after extension length has been determined.
- * C. Hallinan, DS4.COM, Inc.
- */
- /* NetSetIP(pkt, 0xFFFFFFFFL, PORT_BOOTPS, PORT_BOOTPC, sizeof (Bootp_t)); */
- iphdr = pkt; /* We need this later for NetSetIP() */
- pkt += IP_HDR_SIZE;
-
- bp = (Bootp_t *)pkt;
+ bp = (struct bootp *)payload;
bp->bp_op = OP_BOOTREQUEST;
bp->bp_htype = HWT_ETHER;
bp->bp_hlen = HWL_ETHER;
bp->bp_hops = 0;
bp->bp_secs = htons(get_time_ns() >> 30);
- NetWriteIP(&bp->bp_ciaddr, 0);
- NetWriteIP(&bp->bp_yiaddr, 0);
- NetWriteIP(&bp->bp_siaddr, 0);
- NetWriteIP(&bp->bp_giaddr, 0);
- memcpy (bp->bp_chaddr, NetOurEther, 6);
- safe_strncpy (bp->bp_file, BootFile, sizeof(bp->bp_file));
+ net_write_ip(&bp->bp_ciaddr, 0);
+ net_write_ip(&bp->bp_yiaddr, 0);
+ net_write_ip(&bp->bp_siaddr, 0);
+ net_write_ip(&bp->bp_giaddr, 0);
+ memcpy(bp->bp_chaddr, dhcp_con->et->et_src, 6);
- /* Request additional information from the BOOTP/DHCP server */
- ext_len = DhcpExtended((u8 *)bp->bp_vend, DHCP_DISCOVER, 0, 0);
+ bfile = getenv("bootfile");
+ if (bfile)
+ safe_strncpy (bp->bp_file, bfile, sizeof(bp->bp_file));
- /*
- * Bootp ID is the lower 4 bytes of our ethernet address
- * plus the current time in HZ.
- */
- BootpID = ((ulong)NetOurEther[2] << 24)
- | ((ulong)NetOurEther[3] << 16)
- | ((ulong)NetOurEther[4] << 8)
- | (ulong)NetOurEther[5];
- BootpID += (uint32_t)get_time_ns();
- BootpID = htonl(BootpID);
- NetCopyLong(&bp->bp_id, &BootpID);
+ /* Request additional information from the BOOTP/DHCP server */
+ ext_len = dhcp_extended((u8 *)bp->bp_vend, DHCP_DISCOVER, 0, 0);
- /*
- * Calculate proper packet lengths taking into account the
- * variable size of the options field
- */
- pktlen = BOOTP_SIZE - sizeof(bp->bp_vend) + ext_len;
- iplen = BOOTP_HDR_SIZE - sizeof(bp->bp_vend) + ext_len;
- NetSetIP(iphdr, 0xFFFFFFFFL, PORT_BOOTPS, PORT_BOOTPC, iplen);
- NetSetTimeout(SELECT_TIMEOUT * SECOND, BootpTimeout);
+ Bootp_id = (uint32_t)get_time_ns();
+ net_copy_uint32(&bp->bp_id, &Bootp_id);
dhcp_state = SELECTING;
- NetSetHandler(DhcpHandler);
- NetSendPacket(NetTxPacket, pktlen);
+
+ ret = net_udp_send(dhcp_con, sizeof(*bp) + ext_len);
+
+ return ret;
}
-static void DhcpOptionsProcess (uchar * popt, Bootp_t *bp)
+static void dhcp_options_process(unsigned char *popt, struct bootp *bp)
{
- uchar *end = popt + BOOTP_HDR_SIZE;
- int oplen, size;
+ unsigned char *end = popt + sizeof(*bp) + OPT_SIZE;
+ int oplen;
+ IPaddr_t ip;
+ char str[256];
while (popt < end && *popt != 0xff) {
oplen = *(popt + 1);
switch (*popt) {
case 1:
- NetCopyIP (&NetOurSubnetMask, (popt + 2));
+ ip = net_read_ip(popt + 2);
+ net_set_netmask(ip);
break;
case 3:
- NetCopyIP (&NetOurGatewayIP, (popt + 2));
+ ip = net_read_ip(popt + 2);
+ net_set_gateway(ip);
break;
case 6:
- NetCopyIP (&NetOurDNSIP, (popt + 2));
-#ifdef CONFIG_BOOTP_DNS2
- if (*(popt + 1) > 4) {
- NetCopyIP (&NetOurDNS2IP, (popt + 2 + 4));
- }
-#endif
+ ip = net_read_ip(popt + 2);
+ setenv_ip("nameserver", ip);
break;
case 12:
- size = truncate_sz ("Host Name", sizeof (NetOurHostName), oplen);
- memcpy (&NetOurHostName, popt + 2, size);
- NetOurHostName[size] = 0;
+ memcpy(str, popt + 2, oplen);
+ str[oplen] = 0;
+ setenv("hostname", str);
break;
- case 15: /* Ignore Domain Name Option */
+ case 15:
+ memcpy(str, popt + 2, oplen);
+ str[oplen] = 0;
+ setenv("domainname", str);
break;
case 17:
- size = truncate_sz ("Root Path", sizeof (NetOurRootPath), oplen);
- memcpy (&NetOurRootPath, popt + 2, size);
- NetOurRootPath[size] = 0;
+ memcpy(str, popt + 2, oplen);
+ str[oplen] = 0;
+ setenv("rootpath", str);
break;
case 51:
- NetCopyLong (&dhcp_leasetime, (ulong *) (popt + 2));
+ net_copy_uint32 (&dhcp_leasetime, (uint32_t *)(popt + 2));
break;
case 53: /* Ignore Message Type Option */
break;
case 54:
- NetCopyIP (&NetDHCPServerIP, (popt + 2));
+ net_copy_ip(&net_dhcp_server_ip, (popt + 2));
break;
case 58: /* Ignore Renewal Time Option */
break;
@@ -419,10 +292,9 @@ static void DhcpOptionsProcess (uchar * popt, Bootp_t *bp)
* pass the bootp packet pointer into here as the
* second arg
*/
- size = truncate_sz ("Opt Boot File",
- sizeof(bp->bp_file),
- oplen);
- if (bp->bp_file[0] == '\0' && size > 0) {
+ memcpy(str, popt + 2, oplen);
+ str[oplen] = 0;
+ if (bp->bp_file[0] == '\0') {
/*
* only use vendor boot file if we didn't
* receive a boot file in the main non-vendor
@@ -434,8 +306,7 @@ static void DhcpOptionsProcess (uchar * popt, Bootp_t *bp)
*/
printf("*** WARNING: using vendor "
"optional boot file\n");
- memcpy(bp->bp_file, popt + 2, size);
- bp->bp_file[size] = '\0';
+ setenv("bootfile", str);
}
break;
default:
@@ -443,16 +314,16 @@ static void DhcpOptionsProcess (uchar * popt, Bootp_t *bp)
if (dhcp_vendorex_proc (popt))
break;
#endif
- printf ("*** Unhandled DHCP Option in OFFER/ACK: %d\n", *popt);
+ debug("*** Unhandled DHCP Option in OFFER/ACK: %d\n", *popt);
break;
}
popt += oplen + 2; /* Process next option */
}
}
-static int DhcpMessageType(unsigned char *popt)
+static int dhcp_message_type(unsigned char *popt)
{
- if (NetReadLong((ulong*)popt) != htonl(BOOTP_VENDOR_MAGIC))
+ if (net_read_uint32((uint32_t *)popt) != htonl(BOOTP_VENDOR_MAGIC))
return -1;
popt += 4;
@@ -464,76 +335,65 @@ static int DhcpMessageType(unsigned char *popt)
return -1;
}
-static void DhcpSendRequestPkt(Bootp_t *bp_offer)
+static void dhcp_send_request_packet(struct bootp *bp_offer)
{
- uchar *pkt, *iphdr;
- Bootp_t *bp;
- int pktlen, iplen, extlen;
+ struct bootp *bp;
+ int extlen;
IPaddr_t OfferedIP;
+ unsigned char *payload = net_udp_get_payload(dhcp_con);
- debug ("DhcpSendRequestPkt: Sending DHCPREQUEST\n");
- pkt = NetTxPacket;
- memset ((void*)pkt, 0, PKTSIZE);
-
- pkt += NetSetEther(pkt, NetBcastAddr, PROT_IP);
+ debug("%s: Sending DHCPREQUEST\n", __func__);
- iphdr = pkt; /* We'll need this later to set proper pkt size */
- pkt += IP_HDR_SIZE;
-
- bp = (Bootp_t *)pkt;
+ bp = (struct bootp *)payload;
bp->bp_op = OP_BOOTREQUEST;
bp->bp_htype = HWT_ETHER;
bp->bp_hlen = HWL_ETHER;
bp->bp_hops = 0;
/* FIXME what is this? */
// bp->bp_secs = htons(get_timer(0) / CFG_HZ);
- NetCopyIP(&bp->bp_ciaddr, &bp_offer->bp_ciaddr); /* both in network byte order */
- NetCopyIP(&bp->bp_yiaddr, &bp_offer->bp_yiaddr);
- NetCopyIP(&bp->bp_siaddr, &bp_offer->bp_siaddr);
+ net_copy_ip(&bp->bp_ciaddr, &bp_offer->bp_ciaddr); /* both in network byte order */
+ net_copy_ip(&bp->bp_yiaddr, &bp_offer->bp_yiaddr);
+ net_copy_ip(&bp->bp_siaddr, &bp_offer->bp_siaddr);
/*
* RFC3046 requires Relay Agents to discard packets with
* nonzero and offered giaddr
*/
- NetWriteIP(&bp->bp_giaddr, 0);
+ net_write_ip(&bp->bp_giaddr, 0);
- memcpy (bp->bp_chaddr, NetOurEther, 6);
+ memcpy(bp->bp_chaddr, dhcp_con->et->et_src, 6);
/*
* ID is the id of the OFFER packet
*/
- NetCopyLong(&bp->bp_id, &bp_offer->bp_id);
+ net_copy_uint32(&bp->bp_id, &bp_offer->bp_id);
/*
* Copy options from OFFER packet if present
*/
- NetCopyIP(&OfferedIP, &bp->bp_yiaddr);
- extlen = DhcpExtended((u8 *)bp->bp_vend, DHCP_REQUEST, NetDHCPServerIP, OfferedIP);
-
- pktlen = BOOTP_SIZE - sizeof(bp->bp_vend) + extlen;
- iplen = BOOTP_HDR_SIZE - sizeof(bp->bp_vend) + extlen;
- NetSetIP(iphdr, 0xFFFFFFFFL, PORT_BOOTPS, PORT_BOOTPC, iplen);
+ net_copy_ip(&OfferedIP, &bp->bp_yiaddr);
+ extlen = dhcp_extended((u8 *)bp->bp_vend, DHCP_REQUEST, net_dhcp_server_ip, OfferedIP);
- debug ("Transmitting DHCPREQUEST packet: len = %d\n", pktlen);
- NetSendPacket(NetTxPacket, pktlen);
+ debug("Transmitting DHCPREQUEST packet\n");
+ net_udp_send(dhcp_con, sizeof(*bp) + extlen);
}
/*
* Handle DHCP received packets.
*/
-static void
-DhcpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len)
+static void dhcp_handler(char *packet, unsigned int len)
{
- Bootp_t *bp = (Bootp_t *)pkt;
+ char *pkt = net_eth_to_udp_payload(packet);
+ struct udphdr *udp = net_eth_to_udphdr(packet);
+ struct bootp *bp = (struct bootp *)pkt;
- debug ("DHCPHandler: got packet: (src=%d, dst=%d, len=%d) state: %d\n",
- src, dest, len, dhcp_state);
+ len = net_eth_to_udplen(packet);
- if (BootpCheckPkt(pkt, dest, src, len)) /* Filter out pkts we don't want */
- return;
+ debug("DHCPHandler: got packet: (len=%d) state: %d\n",
+ len, dhcp_state);
- debug ("DHCPHandler: got DHCP packet: (src=%d, dst=%d, len=%d) state: %d\n",
- src, dest, len, dhcp_state);
+ if (bootp_check_packet(pkt, ntohs(udp->uh_sport), len)) /* Filter out pkts we don't want */
+ return;
switch (dhcp_state) {
case SELECTING:
@@ -543,69 +403,78 @@ DhcpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len)
* If filename is in format we recognize, assume it is a valid
* OFFER from a server we want.
*/
- debug ("DHCP: state=SELECTING bp_file: \"%s\"\n", bp->bp_file);
-#ifdef CFG_BOOTFILE_PREFIX
- if (strncmp(bp->bp_file,
- CFG_BOOTFILE_PREFIX,
- strlen(CFG_BOOTFILE_PREFIX)) == 0 ) {
-#endif /* CFG_BOOTFILE_PREFIX */
-
- debug ("TRANSITIONING TO REQUESTING STATE\n");
- dhcp_state = REQUESTING;
+ debug ("%s: state SELECTING, bp_file: \"%s\"\n", __func__, bp->bp_file);
+ dhcp_state = REQUESTING;
- if (NetReadLong((ulong*)&bp->bp_vend[0]) == htonl(BOOTP_VENDOR_MAGIC))
- DhcpOptionsProcess((u8 *)&bp->bp_vend[4], bp);
+ if (net_read_uint32((uint32_t *)&bp->bp_vend[0]) == htonl(BOOTP_VENDOR_MAGIC))
+ dhcp_options_process((u8 *)&bp->bp_vend[4], bp);
- BootpCopyNetParams(bp); /* Store net params from reply */
+ bootp_copy_net_params(bp); /* Store net params from reply */
- NetSetTimeout(TIMEOUT * SECOND, BootpTimeout);
- DhcpSendRequestPkt(bp);
-#ifdef CFG_BOOTFILE_PREFIX
- }
-#endif /* CFG_BOOTFILE_PREFIX */
+ dhcp_start = get_time_ns();
+ dhcp_send_request_packet(bp);
- return;
break;
case REQUESTING:
- debug ("DHCP State: REQUESTING\n");
+ debug ("%s: State REQUESTING\n", __func__);
- if ( DhcpMessageType((u8 *)bp->bp_vend) == DHCP_ACK ) {
- if (NetReadLong((ulong*)&bp->bp_vend[0]) == htonl(BOOTP_VENDOR_MAGIC))
- DhcpOptionsProcess((u8 *)&bp->bp_vend[4], bp);
- BootpCopyNetParams(bp); /* Store net params from reply */
+ if (dhcp_message_type((u8 *)bp->bp_vend) == DHCP_ACK ) {
+ if (net_read_uint32((uint32_t *)&bp->bp_vend[0]) == htonl(BOOTP_VENDOR_MAGIC))
+ dhcp_options_process((u8 *)&bp->bp_vend[4], bp);
+ bootp_copy_net_params(bp); /* Store net params from reply */
dhcp_state = BOUND;
puts ("DHCP client bound to address ");
- print_IPaddr(NetOurIP);
+ print_IPaddr(net_get_ip());
putchar('\n');
-
- NetState = NETLOOP_SUCCESS;
return;
}
break;
default:
- puts ("DHCP: INVALID STATE\n");
+ debug("%s: INVALID STATE\n", __func__);
break;
}
-
}
static int do_dhcp(struct command *cmdtp, int argc, char *argv[])
{
- int size;
+ int ret;
+
+ dhcp_con = net_udp_new(0xffffffff, PORT_BOOTPS, dhcp_handler);
+ if (IS_ERR(dhcp_con)) {
+ ret = PTR_ERR(dhcp_con);
+ goto out;
+ }
+
+ ret = net_udp_bind(dhcp_con, PORT_BOOTPC);
+ if (ret)
+ goto out1;
- if (NetLoopInit(DHCP) < 0)
- return 1;
+ net_set_ip(0);
- NetOurIP = 0;
- BootpRequest(); /* Basically same as BOOTP */
+ ret = bootp_request(); /* Basically same as BOOTP */
+ if (ret)
+ goto out1;
- if ((size = NetLoop()) < 0)
- return 1;
+ while (dhcp_state != BOUND) {
+ if (ctrlc())
+ break;
+ net_poll();
+ if (is_timeout(dhcp_start, 3 * SECOND)) {
+ dhcp_start = get_time_ns();
+ printf("T ");
+ ret = bootp_request();
+ if (ret)
+ goto out1;
+ }
+ }
- /* NetLoop ok, update environment */
- netboot_update_env();
+out1:
+ net_unregister(dhcp_con);
+out:
+ if (ret)
+ printf("dhcp failed: %s\n", strerror(-ret));
- return 0;
+ return ret ? 1 : 0;
}
BAREBOX_CMD_START(dhcp)
diff --git a/net/dns.c b/net/dns.c
new file mode 100644
index 0000000000..1ee270b678
--- /dev/null
+++ b/net/dns.c
@@ -0,0 +1,264 @@
+/*
+ * DNS support driver
+ *
+ * Copyright (c) 2008 Pieter Voorthuijsen <pieter.voorthuijsen@prodrive.nl>
+ * Copyright (c) 2009 Robin Getz <rgetz@blackfin.uclinux.org>
+ *
+ * This is a simple DNS implementation for U-Boot. It will use the first IP
+ * in the DNS response as NetServerIP. This can then be used for any other
+ * network related activities.
+ *
+ * The packet handling is partly based on TADNS, original copyrights
+ * follow below.
+ *
+ */
+
+/*
+ * Copyright (c) 2004-2005 Sergey Lyubka <valenok@gmail.com>
+ *
+ * "THE BEER-WARE LICENSE" (Revision 42):
+ * Sergey Lyubka wrote this file. As long as you retain this notice you
+ * can do whatever you want with this stuff. If we meet some day, and you think
+ * this stuff is worth it, you can buy me a beer in return.
+ */
+//#define DEBUG
+#include <common.h>
+#include <command.h>
+#include <net.h>
+#include <clock.h>
+#include <environment.h>
+#include <linux/err.h>
+
+#define DNS_PORT 53
+
+/* http://en.wikipedia.org/wiki/List_of_DNS_record_types */
+enum dns_query_type {
+ DNS_A_RECORD = 0x01,
+ DNS_CNAME_RECORD = 0x05,
+ DNS_MX_RECORD = 0x0f,
+};
+
+/*
+ * DNS network packet
+ */
+struct header {
+ uint16_t tid; /* Transaction ID */
+ uint16_t flags; /* Flags */
+ uint16_t nqueries; /* Questions */
+ uint16_t nanswers; /* Answers */
+ uint16_t nauth; /* Authority PRs */
+ uint16_t nother; /* Other PRs */
+ unsigned char data[1]; /* Data, variable length */
+};
+
+#define STATE_INIT 0
+#define STATE_DONE 1
+
+static struct net_connection *dns_con;
+static uint64_t dns_timer_start;
+static int dns_state;
+static IPaddr_t dns_ip;
+
+static int dns_send(char *name)
+{
+ int ret;
+ struct header *header;
+ enum dns_query_type qtype = DNS_A_RECORD;
+ unsigned char *packet = net_udp_get_payload(dns_con);
+ unsigned char *p, *s, *fullname, *dotptr;
+ const unsigned char *domain;
+
+ /* Prepare DNS packet header */
+ header = (struct header *)packet;
+ header->tid = 1;
+ header->flags = htons(0x100); /* standard query */
+ header->nqueries = htons(1); /* Just one query */
+ header->nanswers = 0;
+ header->nauth = 0;
+ header->nother = 0;
+
+ domain = getenv("domainname");
+
+ if (!strchr(name, '.') && domain && *domain)
+ fullname = asprintf(".%s.%s.", name, domain);
+ else
+ fullname = asprintf(".%s.", name);
+
+ /* replace dots in fullname with chunk len */
+ dotptr = fullname;
+ do {
+ int len;
+
+ s = strchr(dotptr + 1, '.');
+
+ len = s - dotptr - 1;
+
+ *dotptr = len;
+ dotptr = s;
+ } while (*(dotptr + 1));
+ *dotptr = 0;
+//memory_display(fullname, 0, strlen(fullname), 1);
+ strcpy(header->data, fullname);
+
+ p = header->data + strlen(fullname);
+
+ *p++ = 0; /* Mark end of host name */
+ *p++ = 0; /* Some servers require double null */
+ *p++ = (unsigned char)qtype; /* Query Type */
+
+ *p++ = 0;
+ *p++ = 1; /* Class: inet, 0x0001 */
+
+ ret = net_udp_send(dns_con, p - packet);
+
+ free(fullname);
+
+ return ret;
+}
+
+static void dns_handler(char *packet, unsigned len)
+{
+ struct header *header;
+ unsigned char *p, *e, *s;
+ u16 type;
+ int found, stop, dlen;
+ short tmp;
+
+ debug("%s\n", __func__);
+
+ /* We sent 1 query. We want to see more that 1 answer. */
+ header = (struct header *)net_eth_to_udp_payload(packet);;
+ if (ntohs(header->nqueries) != 1)
+ return;
+
+ /* Received 0 answers */
+ if (header->nanswers == 0) {
+ dns_state = STATE_DONE;
+ debug("DNS server returned no answers\n");
+ return;
+ }
+
+ /* Skip host name */
+ s = &header->data[0];
+ e = packet + len;
+ for (p = s; p < e && *p != '\0'; p++)
+ continue;
+
+ /* We sent query class 1, query type 1 */
+ tmp = p[1] | (p[2] << 8);
+ if (&p[5] > e || ntohs(tmp) != DNS_A_RECORD) {
+ debug("DNS response was not A record\n");
+ return;
+ }
+
+ /* Go to the first answer section */
+ p += 5;
+
+ /* Loop through the answers, we want A type answer */
+ for (found = stop = 0; !stop && &p[12] < e; ) {
+
+ /* Skip possible name in CNAME answer */
+ if (*p != 0xc0) {
+ while (*p && &p[12] < e)
+ p++;
+ p--;
+ }
+ debug("Name (Offset in header): %d\n", p[1]);
+
+ tmp = p[2] | (p[3] << 8);
+ type = ntohs(tmp);
+ debug("type = %d\n", type);
+ if (type == DNS_CNAME_RECORD) {
+ /* CNAME answer. shift to the next section */
+ debug("Found canonical name\n");
+ tmp = p[10] | (p[11] << 8);
+ dlen = ntohs(tmp);
+ debug("dlen = %d\n", dlen);
+ p += 12 + dlen;
+ } else if (type == DNS_A_RECORD) {
+ debug("Found A-record\n");
+ found = stop = 1;
+ } else {
+ debug("Unknown type\n");
+ stop = 1;
+ }
+ }
+
+ if (found && &p[12] < e) {
+
+ tmp = p[10] | (p[11] << 8);
+ dlen = ntohs(tmp);
+ p += 12;
+ dns_ip = net_read_ip(p);
+ dns_state = STATE_DONE;
+ }
+}
+
+IPaddr_t resolv(char *host)
+{
+ IPaddr_t ip;
+
+ if (!string_to_ip(host, &ip))
+ return ip;
+
+ dns_ip = 0;
+
+ dns_state = STATE_INIT;
+
+ ip = getenv_ip("nameserver");
+ if (!ip)
+ return 0;
+
+ debug("resolving host %s via nameserver %s\n", host, getenv("nameserver"));
+
+ dns_con = net_udp_new(ip, DNS_PORT, dns_handler);
+ if (IS_ERR(dns_con))
+ return PTR_ERR(dns_con);
+ dns_timer_start = get_time_ns();
+ dns_send(host);
+
+ while (dns_state != STATE_DONE) {
+ if (ctrlc()) {
+ break;
+ }
+ net_poll();
+ if (is_timeout(dns_timer_start, SECOND)) {
+ dns_timer_start = get_time_ns();
+ printf("T ");
+ dns_send(host);
+ }
+ }
+
+ net_unregister(dns_con);
+
+ return dns_ip;
+}
+
+static int do_host(struct command *cmdtp, int argc, char *argv[])
+{
+ IPaddr_t ip;
+
+ if (argc != 2)
+ return COMMAND_ERROR_USAGE;
+
+ ip = resolv(argv[1]);
+ if (!ip)
+ printf("unknown host %s\n", argv[1]);
+ else {
+ printf("%s is at ", argv[1]);
+ print_IPaddr(ip);
+ printf("\n");
+ }
+
+ return 0;
+}
+
+static const __maybe_unused char cmd_host_help[] =
+"Usage: host <hostname>\n";
+
+BAREBOX_CMD_START(host)
+ .cmd = do_host,
+ .usage = "resolve a hostname",
+ BAREBOX_CMD_HELP(cmd_host_help)
+BAREBOX_CMD_END
+
diff --git a/net/eth.c b/net/eth.c
index 7570198a17..4d58191214 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -36,7 +36,13 @@ static LIST_HEAD(netdev_list);
void eth_set_current(struct eth_device *eth)
{
+ if (eth_current && eth_current->active) {
+ eth_current->halt(eth_current);
+ eth_current->active = 0;
+ }
+
eth_current = eth;
+ net_update_env();
}
struct eth_device * eth_get_current(void)
@@ -57,37 +63,37 @@ struct eth_device *eth_get_byname(char *ethname)
return NULL;
}
-int eth_open(void)
-{
- if (!eth_current)
- return -ENODEV;
-
- return eth_current->open(eth_current);
-}
-
-void eth_halt(void)
-{
- if (!eth_current)
- return;
-
- eth_current->halt(eth_current);
-
- eth_current->state = ETH_STATE_PASSIVE;
-}
-
int eth_send(void *packet, int length)
{
+ int ret;
+
if (!eth_current)
return -ENODEV;
+ if (!eth_current->active) {
+ ret = eth_current->open(eth_current);
+ if (ret)
+ return ret;
+ eth_current->active = 1;
+ }
+
return eth_current->send(eth_current, packet, length);
}
int eth_rx(void)
{
+ int ret;
+
if (!eth_current)
return -ENODEV;
+ if (!eth_current->active) {
+ ret = eth_current->open(eth_current);
+ if (ret)
+ return ret;
+ eth_current->active = 1;
+ }
+
return eth_current->recv(eth_current);
}
@@ -96,26 +102,37 @@ static int eth_set_ethaddr(struct device_d *dev, struct param_d *param, const ch
struct eth_device *edev = dev->type_data;
char ethaddr[sizeof("xx:xx:xx:xx:xx:xx")];
+ if (!val)
+ return dev_param_set_generic(dev, param, NULL);
+
if (string_to_ethaddr(val, ethaddr) < 0)
return -EINVAL;
- free(param->value);
- param->value = strdup(val);
+ dev_param_set_generic(dev, param, val);
edev->set_ethaddr(edev, ethaddr);
+ if (edev == eth_current)
+ net_update_env();
+
return 0;
}
static int eth_set_ipaddr(struct device_d *dev, struct param_d *param, const char *val)
{
+ struct eth_device *edev = dev->type_data;
IPaddr_t ip;
+ if (!val)
+ return dev_param_set_generic(dev, param, NULL);
+
if (string_to_ip(val, &ip))
return -EINVAL;
- free(param->value);
- param->value = strdup(val);
+ dev_param_set_generic(dev, param, val);
+
+ if (edev == eth_current)
+ net_update_env();
return 0;
}
@@ -135,21 +152,11 @@ int eth_register(struct eth_device *edev)
register_device(&edev->dev);
dev->type_data = edev;
- edev->param_ip.name = "ipaddr";
- edev->param_ip.set = &eth_set_ipaddr;
- edev->param_ethaddr.name = "ethaddr";
- edev->param_ethaddr.set = &eth_set_ethaddr;
- edev->param_gateway.name = "gateway";
- edev->param_gateway.set = &eth_set_ipaddr;
- edev->param_netmask.name = "netmask";
- edev->param_netmask.set = &eth_set_ipaddr;
- edev->param_serverip.name = "serverip";
- edev->param_serverip.set = &eth_set_ipaddr;
- dev_add_param(dev, &edev->param_ip);
- dev_add_param(dev, &edev->param_ethaddr);
- dev_add_param(dev, &edev->param_gateway);
- dev_add_param(dev, &edev->param_netmask);
- dev_add_param(dev, &edev->param_serverip);
+ dev_add_param(dev, "ipaddr", eth_set_ipaddr, NULL, 0);
+ dev_add_param(dev, "ethaddr", eth_set_ethaddr, NULL, 0);
+ dev_add_param(dev, "gateway", eth_set_ipaddr, NULL, 0);
+ dev_add_param(dev, "netmask", eth_set_ipaddr, NULL, 0);
+ dev_add_param(dev, "serverip", eth_set_ipaddr, NULL, 0);
edev->init(edev);
@@ -157,7 +164,7 @@ int eth_register(struct eth_device *edev)
if (edev->get_ethaddr(edev, ethaddr) == 0) {
ethaddr_to_string(ethaddr, ethaddr_str);
- printf("got MAC address from EEPROM: %s\n",ethaddr_str);
+ printf("got MAC address from EEPROM: %s\n",&ethaddr_str);
dev_set_param(dev, "ethaddr", ethaddr_str);
}
@@ -169,20 +176,9 @@ int eth_register(struct eth_device *edev)
void eth_unregister(struct eth_device *edev)
{
- if (edev->param_ip.value)
- free(edev->param_ip.value);
- if (edev->param_ethaddr.value)
- free(edev->param_ethaddr.value);
- if (edev->param_gateway.value)
- free(edev->param_gateway.value);
- if (edev->param_netmask.value)
- free(edev->param_netmask.value);
- if (edev->param_serverip.value)
- free(edev->param_serverip.value);
-
- if (eth_current == edev)
- eth_current = NULL;
+ dev_remove_parameters(&edev->dev);
list_del(&edev->list);
}
+
diff --git a/net/net.c b/net/net.c
index 4554d49e36..4305c727f4 100644
--- a/net/net.c
+++ b/net/net.c
@@ -1,73 +1,31 @@
/*
- * Copied from Linux Monitor (LiMon) - Networking.
+ * net.c - barebox networking support
*
- * Copyright 1994 - 2000 Neil Russell.
- * (See License)
- * Copyright 2000 Roland Borde
- * Copyright 2000 Paolo Scaffardi
- * Copyright 2000-2002 Wolfgang Denk, wd@denx.de
- */
-
-/*
- * General Desription:
- *
- * The user interface supports commands for BOOTP, RARP, and TFTP.
- * Also, we support ARP internally. Depending on available data,
- * these interact as follows:
- *
- * BOOTP:
- *
- * Prerequisites: - own ethernet address
- * We want: - own IP address
- * - TFTP server IP address
- * - name of bootfile
- * Next step: ARP
- *
- * RARP:
- *
- * Prerequisites: - own ethernet address
- * We want: - own IP address
- * - TFTP server IP address
- * Next step: ARP
- *
- * ARP:
- *
- * Prerequisites: - own ethernet address
- * - own IP address
- * - TFTP server IP address
- * We want: - TFTP server ethernet address
- * Next step: TFTP
+ * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
*
- * DHCP:
+ * based on U-Boot (LiMon) code
*
- * Prerequisites: - own ethernet address
- * We want: - IP, Netmask, ServerIP, Gateway IP
- * - bootfilename, lease time
- * Next step: - TFTP
+ * Copyright 1994 - 2000 Neil Russell.
+ * Copyright 2000 Roland Borde
+ * Copyright 2000 Paolo Scaffardi
+ * Copyright 2000-2002 Wolfgang Denk, wd@denx.de
*
- * TFTP:
+ * See file CREDITS for list of people who contributed to this
+ * project.
*
- * Prerequisites: - own ethernet address
- * - own IP address
- * - TFTP server IP address
- * - TFTP server ethernet address
- * - name of bootfile (if unknown, we use a default name
- * derived from our own IP address)
- * We want: - load the boot file
- * Next step: none
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
*
- * NFS:
- *
- * Prerequisites: - own ethernet address
- * - own IP address
- * - name of bootfile (if unknown, we use a default name
- * derived from our own IP address)
- * We want: - load the boot file
- * Next step: none
+ * 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>
#include <clock.h>
#include <watchdog.h>
@@ -77,885 +35,614 @@
#include <net.h>
#include <driver.h>
#include <errno.h>
+#include <malloc.h>
+#include <init.h>
#include <linux/ctype.h>
-#include "tftp.h"
-#include "rarp.h"
-#include "nfs.h"
-
-#define ARP_TIMEOUT (5 * SECOND) /* Seconds before trying ARP again */
-#ifndef CONFIG_NET_RETRY_COUNT
-# define ARP_TIMEOUT_COUNT 5 /* # of timeouts before giving up */
-#else
-# define ARP_TIMEOUT_COUNT (CONFIG_NET_RETRY_COUNT)
-#endif
+#include <linux/err.h>
+static IPaddr_t net_netmask; /* Our subnet mask (0=unknown) */
+static IPaddr_t net_gateway; /* Our gateways IP address */
-/** BOOTP EXTENTIONS **/
+static unsigned char net_ether[6]; /* Our ethernet address */
+static IPaddr_t net_ip; /* Our IP addr (0 = unknown) */
+static IPaddr_t net_serverip; /* Our IP addr (0 = unknown) */
-IPaddr_t NetOurSubnetMask=0; /* Our subnet mask (0=unknown) */
-IPaddr_t NetOurGatewayIP=0; /* Our gateways IP address */
-IPaddr_t NetOurDNSIP=0; /* Our DNS IP address */
-#ifdef CONFIG_BOOTP_DNS2
-IPaddr_t NetOurDNS2IP=0; /* Our 2nd DNS IP address */
-#endif
-char NetOurNISDomain[32]={0,}; /* Our NIS domain */
-char NetOurHostName[32]={0,}; /* Our hostname */
-char NetOurRootPath[64]={0,}; /* Our bootpath */
+unsigned char *NetRxPackets[PKTBUFSRX]; /* Receive packets */
+static unsigned int net_ip_id;
-/** END OF BOOTP EXTENTIONS **/
+void net_update_env(void)
+{
+ struct eth_device *edev = eth_get_current();
-ulong NetBootFileXferSize; /* The actual transferred size of the bootfile (in bytes) */
-uchar NetOurEther[6]; /* Our ethernet address */
-uchar NetServerEther[6] = /* Boot server enet address */
- { 0, 0, 0, 0, 0, 0 };
-IPaddr_t NetOurIP; /* Our IP addr (0 = unknown) */
-IPaddr_t NetServerIP; /* Our IP addr (0 = unknown) */
-uchar *NetRxPkt; /* Current receive packet */
-int NetRxPktLen; /* Current rx packet length */
-unsigned NetIPID; /* IP packet ID */
-uchar NetBcastAddr[6] = /* Ethernet bcast address */
- { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
-uchar NetEtherNullAddr[6] =
- { 0, 0, 0, 0, 0, 0 };
-int NetState; /* Network loop state */
+ net_ip = dev_get_param_ip(&edev->dev, "ipaddr");
+ net_serverip = dev_get_param_ip(&edev->dev, "serverip");
+ net_gateway = dev_get_param_ip(&edev->dev, "gateway");
+ net_netmask = dev_get_param_ip(&edev->dev, "netmask");
-/* XXX in both little & big endian machines 0xFFFF == ntohs(-1) */
-ushort NetOurVLAN = 0xFFFF; /* default is without VLAN */
-ushort NetOurNativeVLAN = 0xFFFF; /* ditto */
+ string_to_ethaddr(dev_get_param(&edev->dev, "ethaddr"),
+ net_ether);
+}
-char BootFile[128]; /* Boot File name */
+int net_checksum_ok(unsigned char *ptr, int len)
+{
+ return net_checksum(ptr, len) + 1;
+}
-uchar PktBuf[(PKTBUFSRX+1) * PKTSIZE_ALIGN + PKTALIGN];
+uint16_t net_checksum(unsigned char *ptr, int len)
+{
+ uint32_t xsum = 0;
+ uint16_t *p = (uint16_t *)ptr;
-uchar *NetRxPackets[PKTBUFSRX]; /* Receive packets */
+ if (len & 1)
+ ptr[len] = 0;
-static rxhand_f *packetHandler; /* Current RX packet handler */
-static thand_f *timeHandler; /* Current timeout handler */
-static uint64_t timeStart; /* Time base value */
-static uint64_t timeDelta; /* Current timeout value */
-uchar *NetTxPacket = 0; /* THE transmit packet */
+ len = (len + 1) >> 1;
-static int net_check_prereq (proto_t protocol);
+ while (len-- > 0)
+ xsum += *p++;
-/**********************************************************************/
+ xsum = (xsum & 0xffff) + (xsum >> 16);
+ xsum = (xsum & 0xffff) + (xsum >> 16);
+ return xsum & 0xffff;
+}
-IPaddr_t NetArpWaitPacketIP;
-IPaddr_t NetArpWaitReplyIP;
-uchar *NetArpWaitPacketMAC; /* MAC address of waiting packet's destination */
-uchar *NetArpWaitTxPacket; /* THE transmit packet */
-int NetArpWaitTxPacketSize;
-uchar NetArpWaitPacketBuf[PKTSIZE_ALIGN + PKTALIGN];
-uint64_t NetArpWaitTimerStart;
+char *ip_to_string (IPaddr_t x, char *s)
+{
+ x = ntohl (x);
+ sprintf (s, "%d.%d.%d.%d",
+ (int) ((x >> 24) & 0xff),
+ (int) ((x >> 16) & 0xff),
+ (int) ((x >> 8) & 0xff), (int) ((x >> 0) & 0xff)
+ );
+ return s;
+}
-void ArpRequest (void)
+int string_to_ip(const char *s, IPaddr_t *ip)
{
+ IPaddr_t addr = 0;
+ char *e;
int i;
- uchar *pkt;
- ARP_t *arp;
-
- pr_debug("ARP broadcast\n");
- pkt = NetTxPacket;
+ if (!s)
+ return -EINVAL;
- pkt += NetSetEther (pkt, NetBcastAddr, PROT_ARP);
+ for (i = 0; i < 4; i++) {
+ unsigned long val;
- arp = (ARP_t *) pkt;
+ if (!isdigit(*s))
+ return -EINVAL;
- arp->ar_hrd = htons (ARP_ETHER);
- arp->ar_pro = htons (PROT_IP);
- arp->ar_hln = 6;
- arp->ar_pln = 4;
- arp->ar_op = htons (ARPOP_REQUEST);
+ val = simple_strtoul(s, &e, 10);
+ addr <<= 8;
+ addr |= (val & 0xFF);
- memcpy (&arp->ar_data[0], NetOurEther, 6); /* source ET addr */
- NetWriteIP ((uchar *) & arp->ar_data[6], NetOurIP); /* source IP addr */
- for (i = 10; i < 16; ++i) {
- arp->ar_data[i] = 0; /* dest ET addr = 0 */
- }
+ if (*e != '.' && i != 3)
+ return -EINVAL;
- if ((NetArpWaitPacketIP & NetOurSubnetMask) !=
- (NetOurIP & NetOurSubnetMask)) {
- if (NetOurGatewayIP == 0) {
- puts ("## Warning: gatewayip needed but not set\n");
- NetArpWaitReplyIP = NetArpWaitPacketIP;
- } else {
- NetArpWaitReplyIP = NetOurGatewayIP;
- }
- } else {
- NetArpWaitReplyIP = NetArpWaitPacketIP;
+ s = e + 1;
}
- NetWriteIP ((uchar *) & arp->ar_data[16], NetArpWaitReplyIP);
- (void) eth_send (NetTxPacket, (pkt - NetTxPacket) + ARP_HDR_SIZE);
+ *ip = htonl(addr);
+ return 0;
}
-/**********************************************************************/
-/*
- * Main network processing loop.
- */
-
-int NetLoopInit(proto_t protocol)
+IPaddr_t getenv_ip(const char *name)
{
- struct eth_device *eth_current = eth_get_current();
IPaddr_t ip;
- int ret;
- int i;
-
- if (!eth_current) {
- printf("Current ethernet device not set!\n");
- return -1;
- }
+ const char *var = getenv(name);
- ip = dev_get_param_ip(&eth_current->dev, "ipaddr");
- NetCopyIP(&NetOurIP, &ip);
-
- /* XXX problem with bss workaround */
- NetArpWaitPacketMAC = NULL;
- NetArpWaitTxPacket = NULL;
- NetArpWaitPacketIP = 0;
- NetArpWaitReplyIP = 0;
-
- /*
- * Setup packet buffers, aligned correctly.
- */
- NetTxPacket = &PktBuf[0] + (PKTALIGN - 1);
- NetTxPacket -= (ulong)NetTxPacket % PKTALIGN;
- for (i = 0; i < PKTBUFSRX; i++) {
- NetRxPackets[i] = NetTxPacket + (i+1)*PKTSIZE_ALIGN;
- }
-
- NetArpWaitTxPacket = &NetArpWaitPacketBuf[0] + (PKTALIGN - 1);
- NetArpWaitTxPacket -= (ulong)NetArpWaitTxPacket % PKTALIGN;
- NetArpWaitTxPacketSize = 0;
+ if (!var)
+ return 0;
- if (eth_open() < 0)
- return -1;
+ string_to_ip(var, &ip);
- string_to_ethaddr(dev_get_param(&eth_get_current()->dev, "ethaddr"),
- NetOurEther);
+ return ip;
+}
- NetState = NETLOOP_CONTINUE;
+int setenv_ip(const char *name, IPaddr_t ip)
+{
+ char str[sizeof("xxx.xxx.xxx.xxx")];
- NetOurGatewayIP = dev_get_param_ip(&eth_current->dev, "gateway");
- NetOurSubnetMask = dev_get_param_ip(&eth_current->dev, "netmask");
- NetOurVLAN = getenv_VLAN("vlan");
- NetOurNativeVLAN = getenv_VLAN("nvlan");
- NetServerIP = dev_get_param_ip(&eth_current->dev, "serverip");
+ ip_to_string(ip, str);
- ret = net_check_prereq(protocol);
- if (ret)
- eth_halt();
+ setenv(name, str);
- return ret;
+ return 0;
}
-int NetLoop(void)
+void print_IPaddr (IPaddr_t x)
{
- /*
- * Start the ball rolling with the given start function. From
- * here on, this code is a state machine driven by received
- * packets and timer events.
- */
+ char tmp[16];
- NetBootFileXferSize = 0;
+ ip_to_string (x, tmp);
- /*
- * Main packet reception loop. Loop receiving packets until
- * someone sets `NetState' to a state that terminates.
- */
- for (;;) {
- WATCHDOG_RESET();
-#ifdef CONFIG_SHOW_ACTIVITY
- {
- extern void show_activity(int arg);
- show_activity(1);
- }
-#endif
- /*
- * Check the ethernet for a new packet. The ethernet
- * receive routine will process it.
- */
- eth_rx();
-
- /*
- * Abort if ctrl-c was pressed.
- */
- if (ctrlc()) {
- eth_halt();
- puts ("\nAbort\n");
- return -1;
- }
+ puts (tmp);
+}
- /* check for arp timeout */
- if (NetArpWaitPacketIP &&
- is_timeout(NetArpWaitTimerStart, ARP_TIMEOUT)) {
- NetArpWaitTimerStart = get_time_ns();
- ArpRequest();
- }
+int string_to_ethaddr(const char *str, char *enetaddr)
+{
+ int reg;
+ char *e;
- /*
- * Check for a timeout, and run the timeout handler
- * if we have one.
- */
- if (timeHandler && is_timeout(timeStart, timeDelta)) {
- thand_f *x;
- x = timeHandler;
- timeHandler = (thand_f *)0;
- (*x)();
- }
+ if (!str || strlen(str) != 17)
+ return -1;
+ if (str[2] != ':' || str[5] != ':' || str[8] != ':' ||
+ str[11] != ':' || str[14] != ':')
+ return -1;
- switch (NetState) {
- case NETLOOP_SUCCESS:
- if (NetBootFileXferSize > 0) {
- char buf[10];
- printf("Bytes transferred = %ld (%lx hex)\n",
- NetBootFileXferSize,
- NetBootFileXferSize);
- sprintf(buf, "0x%lx", NetBootFileXferSize);
- setenv("filesize", buf);
- }
- eth_halt();
- return NetBootFileXferSize;
-
- case NETLOOP_FAIL:
- eth_halt();
- return -1;
- }
+ for (reg = 0; reg < 6; ++reg) {
+ enetaddr[reg] = simple_strtoul (str, &e, 16);
+ str = e + 1;
}
-}
-/**********************************************************************/
-/*
- * Miscelaneous bits.
- */
+ return 0;
+}
-void
-NetSetHandler(rxhand_f * f)
+void ethaddr_to_string(const unsigned char *enetaddr, char *str)
{
- packetHandler = f;
+ sprintf(str, "%02X:%02X:%02X:%02X:%02X:%02X",
+ enetaddr[0], enetaddr[1], enetaddr[2], enetaddr[3],
+ enetaddr[4], enetaddr[5]);
}
+static unsigned char *arp_ether;
+static IPaddr_t arp_wait_ip;
-void
-NetSetTimeout(uint64_t iv, thand_f * f)
+static void arp_handler(struct arprequest *arp)
{
- if (iv == 0) {
- timeHandler = (thand_f *)0;
- } else {
- timeHandler = f;
- timeStart = get_time_ns();
- timeDelta = iv;
- }
-}
+ IPaddr_t tmp;
+ /* are we waiting for a reply */
+ if (!arp_wait_ip)
+ return;
-void
-NetSendPacket(uchar * pkt, int len)
-{
- (void) eth_send(pkt, len);
+ tmp = net_read_ip(&arp->ar_data[6]);
+
+ /* matched waiting packet's address */
+ if (tmp == arp_wait_ip) {
+ /* save address for later use */
+ memcpy(arp_ether, &arp->ar_data[0], 6);
+
+ /* no arp request pending now */
+ arp_wait_ip = 0;
+ }
}
-int
-NetSendUDPPacket(uchar *ether, IPaddr_t dest, int dport, int sport, int len)
+int arp_request(IPaddr_t dest, unsigned char *ether)
{
- uchar *pkt;
+ char *pkt;
+ struct arprequest *arp;
+ uint64_t arp_start;
+ static char *arp_packet;
+ struct ethernet *et;
+
+ if (!arp_packet) {
+ arp_packet = net_alloc_packet();
+ if (!arp_packet)
+ return -ENOMEM;
+ }
- /* convert to new style broadcast */
- if (dest == 0)
- dest = 0xFFFFFFFF;
+ pkt = arp_packet;
+ et = (struct ethernet *)arp_packet;
- /* if broadcast, make the ether address a broadcast and don't do ARP */
- if (dest == 0xFFFFFFFF)
- ether = NetBcastAddr;
+ arp_wait_ip = dest;
- /* if MAC address was not discovered yet, save the packet and do an ARP request */
- if (memcmp(ether, NetEtherNullAddr, 6) == 0) {
- pr_debug("sending ARP for %08lx\n", dest);
+ pr_debug("ARP broadcast\n");
- NetArpWaitPacketIP = dest;
- NetArpWaitPacketMAC = ether;
+ memset(et->et_dest, 0xff, 6);
+ memcpy(et->et_src, net_ether, 6);
+ et->et_protlen = htons(PROT_ARP);
- pkt = NetArpWaitTxPacket;
- pkt += NetSetEther (pkt, NetArpWaitPacketMAC, PROT_IP);
+ arp = (struct arprequest *)(pkt + ETHER_HDR_SIZE);
- NetSetIP (pkt, dest, dport, sport, len);
- memcpy(pkt + IP_HDR_SIZE, (uchar *)NetTxPacket + (pkt - (uchar *)NetArpWaitTxPacket) + IP_HDR_SIZE, len);
+ arp->ar_hrd = htons(ARP_ETHER);
+ arp->ar_pro = htons(PROT_IP);
+ arp->ar_hln = 6;
+ arp->ar_pln = 4;
+ arp->ar_op = htons(ARPOP_REQUEST);
- /* size of the waiting packet */
- NetArpWaitTxPacketSize = (pkt - NetArpWaitTxPacket) + IP_HDR_SIZE + len;
+ memcpy(arp->ar_data, net_ether, 6); /* source ET addr */
+ net_write_ip(arp->ar_data + 6, net_ip); /* source IP addr */
+ memset(arp->ar_data + 10, 0, 6); /* dest ET addr = 0 */
- /* and do the ARP request */
- NetArpWaitTimerStart = get_time_ns();
- ArpRequest();
- return 1; /* waiting */
+ if ((dest & net_netmask) != (net_ip & net_netmask)) {
+ if (!net_gateway)
+ arp_wait_ip = dest;
+ else
+ arp_wait_ip = net_gateway;
+ } else {
+ arp_wait_ip = dest;
}
- pr_debug("sending UDP to %08lx/%02x:%02x:%02x:%02x:%02x:%02x\n",
- dest, ether[0], ether[1], ether[2], ether[3], ether[4], ether[5]);
-
- pkt = (uchar *)NetTxPacket;
- pkt += NetSetEther (pkt, ether, PROT_IP);
- NetSetIP (pkt, dest, dport, sport, len);
- (void) eth_send(NetTxPacket, (pkt - NetTxPacket) + IP_HDR_SIZE + len);
+ net_write_ip(arp->ar_data + 16, arp_wait_ip);
- return 0; /* transmitted */
-}
+ arp_ether = ether;
-void
-NetReceive(uchar * inpkt, int len)
-{
- Ethernet_t *et;
- IP_t *ip;
- ARP_t *arp;
- IPaddr_t tmp;
- int x;
- uchar *pkt;
- ushort cti = 0, vlanid = VLAN_NONE, myvlanid, mynvlanid;
+ eth_send(arp_packet, ETHER_HDR_SIZE + ARP_HDR_SIZE);
+ arp_start = get_time_ns();
- pr_debug("packet received\n");
+ while (arp_wait_ip) {
+ if (ctrlc())
+ return -EINTR;
- NetRxPkt = inpkt;
- NetRxPktLen = len;
- et = (Ethernet_t *)inpkt;
+ if (is_timeout(arp_start, 3 * SECOND)) {
+ printf("T ");
+ arp_start = get_time_ns();
+ eth_send(arp_packet, ETHER_HDR_SIZE + ARP_HDR_SIZE);
+ }
- /* too small packet? */
- if (len < ETHER_HDR_SIZE)
- return;
+ net_poll();
+ }
- myvlanid = ntohs(NetOurVLAN);
- if (myvlanid == (ushort)-1)
- myvlanid = VLAN_NONE;
- mynvlanid = ntohs(NetOurNativeVLAN);
- if (mynvlanid == (ushort)-1)
- mynvlanid = VLAN_NONE;
+ pr_debug("Got ARP REPLY, set server/gtwy eth addr (%02x:%02x:%02x:%02x:%02x:%02x)\n",
+ ether[0], ether[1],
+ ether[2], ether[3],
+ ether[4], ether[5]);
+ return 0;
+}
- x = ntohs(et->et_protlen);
+void net_poll(void)
+{
+ eth_rx();
+}
- pr_debug("packet received\n");
+static uint16_t net_udp_new_localport(void)
+{
+ static uint16_t localport;
- if (x < 1514) {
- /*
- * Got a 802 packet. Check the other protocol field.
- */
- x = ntohs(et->et_prot);
+ localport++;
- ip = (IP_t *)(inpkt + E802_HDR_SIZE);
- len -= E802_HDR_SIZE;
+ if (localport < 1024)
+ localport = 1024;
- } else if (x != PROT_VLAN) { /* normal packet */
- ip = (IP_t *)(inpkt + ETHER_HDR_SIZE);
- len -= ETHER_HDR_SIZE;
+ return localport;
+}
- } else { /* VLAN packet */
- VLAN_Ethernet_t *vet = (VLAN_Ethernet_t *)et;
+IPaddr_t net_get_serverip(void)
+{
+ return net_serverip;
+}
- pr_debug("VLAN packet received\n");
+void net_set_serverip(IPaddr_t ip)
+{
+ struct eth_device *edev = eth_get_current();
- /* too small packet? */
- if (len < VLAN_ETHER_HDR_SIZE)
- return;
+ net_serverip = ip;
+ dev_set_param_ip(&edev->dev, "serverip", net_serverip);
+}
- /* if no VLAN active */
- if ((ntohs(NetOurVLAN) & VLAN_IDMASK) == VLAN_NONE
- )
- return;
+void net_set_ip(IPaddr_t ip)
+{
+ struct eth_device *edev = eth_get_current();
- cti = ntohs(vet->vet_tag);
- vlanid = cti & VLAN_IDMASK;
- x = ntohs(vet->vet_type);
+ net_ip = ip;
+ dev_set_param_ip(&edev->dev, "ipaddr", net_ip);
+}
- ip = (IP_t *)(inpkt + VLAN_ETHER_HDR_SIZE);
- len -= VLAN_ETHER_HDR_SIZE;
- }
+IPaddr_t net_get_ip(void)
+{
+ return net_ip;
+}
- pr_debug("Receive from protocol 0x%x\n", x);
+void net_set_netmask(IPaddr_t nm)
+{
+ struct eth_device *edev = eth_get_current();
- if ((myvlanid & VLAN_IDMASK) != VLAN_NONE) {
- if (vlanid == VLAN_NONE)
- vlanid = (mynvlanid & VLAN_IDMASK);
- /* not matched? */
- if (vlanid != (myvlanid & VLAN_IDMASK))
- return;
- }
+ net_netmask = nm;
+ dev_set_param_ip(&edev->dev, "netmask", net_netmask);
+}
- switch (x) {
+void net_set_gateway(IPaddr_t gw)
+{
+ struct eth_device *edev = eth_get_current();
- case PROT_ARP:
- /*
- * We have to deal with two types of ARP packets:
- * - REQUEST packets will be answered by sending our
- * IP address - if we know it.
- * - REPLY packets are expected only after we asked
- * for the TFTP server's or the gateway's ethernet
- * address; so if we receive such a packet, we set
- * the server ethernet address
- */
- pr_debug("Got ARP\n");
-
- arp = (ARP_t *)ip;
- if (len < ARP_HDR_SIZE) {
- printf("bad length %d < %d\n", len, ARP_HDR_SIZE);
- return;
- }
- if (ntohs(arp->ar_hrd) != ARP_ETHER) {
- return;
- }
- if (ntohs(arp->ar_pro) != PROT_IP) {
- return;
- }
- if (arp->ar_hln != 6) {
- return;
- }
- if (arp->ar_pln != 4) {
- return;
- }
+ net_gateway = gw;
+ dev_set_param_ip(&edev->dev, "gateway", net_gateway);
+}
- if (NetOurIP == 0) {
- return;
- }
+static LIST_HEAD(connection_list);
- if (NetReadIP(&arp->ar_data[16]) != NetOurIP) {
- return;
- }
+static struct net_connection *net_new(IPaddr_t dest, rx_handler_f *handler)
+{
+ struct net_connection *con;
+ int ret;
- switch (ntohs(arp->ar_op)) {
- case ARPOP_REQUEST: /* reply with our IP address */
- pr_debug("Got ARP REQUEST, return our IP\n");
-
- pkt = (uchar *)et;
- pkt += NetSetEther(pkt, et->et_src, PROT_ARP);
- arp->ar_op = htons(ARPOP_REPLY);
- memcpy (&arp->ar_data[10], &arp->ar_data[0], 6);
- NetCopyIP(&arp->ar_data[16], &arp->ar_data[6]);
- memcpy (&arp->ar_data[ 0], NetOurEther, 6);
- NetCopyIP(&arp->ar_data[ 6], &NetOurIP);
- memcpy(NetTxPacket, et, (pkt - (uchar *)et) + ARP_HDR_SIZE);
- eth_send((uchar *)NetTxPacket, (pkt - (uchar *)et) + ARP_HDR_SIZE);
- return;
-
- case ARPOP_REPLY: /* arp reply */
- /* are we waiting for a reply */
- if (!NetArpWaitPacketIP || !NetArpWaitPacketMAC)
- break;
- pr_debug("Got ARP REPLY, set server/gtwy eth addr (%02x:%02x:%02x:%02x:%02x:%02x)\n",
- arp->ar_data[0], arp->ar_data[1],
- arp->ar_data[2], arp->ar_data[3],
- arp->ar_data[4], arp->ar_data[5]);
-
- tmp = NetReadIP(&arp->ar_data[6]);
-
- /* matched waiting packet's address */
- if (tmp == NetArpWaitReplyIP) {
- pr_debug("Got it\n");
-
- /* save address for later use */
- memcpy(NetArpWaitPacketMAC, &arp->ar_data[0], 6);
-
- /* modify header, and transmit it */
- memcpy(((Ethernet_t *)NetArpWaitTxPacket)->et_dest, NetArpWaitPacketMAC, 6);
- (void) eth_send(NetArpWaitTxPacket, NetArpWaitTxPacketSize);
-
- /* no arp request pending now */
- NetArpWaitPacketIP = 0;
- NetArpWaitTxPacketSize = 0;
- NetArpWaitPacketMAC = NULL;
-
- }
- return;
- default:
- pr_debug("Unexpected ARP opcode 0x%x\n", ntohs(arp->ar_op));
- return;
- }
- break;
+ if (!is_valid_ether_addr(net_ether))
+ return ERR_PTR(-ENETDOWN);
- case PROT_RARP:
- pr_debug("Got RARP\n");
+ /* If we don't have an ip only broadcast is allowed */
+ if (!net_ip && dest != 0xffffffff)
+ return ERR_PTR(-ENETDOWN);
- arp = (ARP_t *)ip;
- if (len < ARP_HDR_SIZE) {
- printf("bad length %d < %d\n", len, ARP_HDR_SIZE);
- return;
- }
+ con = xzalloc(sizeof(*con));
+ con->packet = memalign(32, PKTSIZE);
+ memset(con->packet, 0, PKTSIZE);
- if ((ntohs(arp->ar_op) != RARPOP_REPLY) ||
- (ntohs(arp->ar_hrd) != ARP_ETHER) ||
- (ntohs(arp->ar_pro) != PROT_IP) ||
- (arp->ar_hln != 6) || (arp->ar_pln != 4)) {
+ con->et = (struct ethernet *)con->packet;
+ con->ip = (struct iphdr *)(con->packet + ETHER_HDR_SIZE);
+ con->udp = (struct udphdr *)(con->packet + ETHER_HDR_SIZE + sizeof(struct iphdr));
+ con->icmp = (struct icmphdr *)(con->packet + ETHER_HDR_SIZE + sizeof(struct iphdr));
+ con->handler = handler;
- puts ("invalid RARP header\n");
- } else {
- NetCopyIP(&NetOurIP, &arp->ar_data[16]);
- if (NetServerIP == 0)
- NetCopyIP(&NetServerIP, &arp->ar_data[ 6]);
- memcpy (NetServerEther, &arp->ar_data[ 0], 6);
+ if (dest == 0xffffffff) {
+ memset(con->et->et_dest, 0xff, 6);
+ } else {
+ ret = arp_request(dest, con->et->et_dest);
+ if (ret)
+ goto out;
+ }
- (*packetHandler)(0,0,0,0);
- }
- break;
+ con->et->et_protlen = htons(PROT_IP);
+ memcpy(con->et->et_src, net_ether, 6);
- case PROT_IP:
- pr_debug("Got IP\n");
+ con->ip->hl_v = 0x45;
+ con->ip->tos = 0;
+ con->ip->frag_off = htons(0x4000); /* No fragmentation */;
+ con->ip->ttl = 255;
+ net_copy_ip(&con->ip->daddr, &dest);
+ net_copy_ip(&con->ip->saddr, &net_ip);
- if (len < IP_HDR_SIZE) {
- debug ("len bad %d < %d\n", len, IP_HDR_SIZE);
- return;
- }
- if (len < ntohs(ip->ip_len)) {
- printf("len bad %d < %d\n", len, ntohs(ip->ip_len));
- return;
- }
- len = ntohs(ip->ip_len);
+ list_add_tail(&con->list, &connection_list);
- pr_debug("len=%d, v=%02x\n", len, ip->ip_hl_v & 0xff);
+ return con;
+out:
+ free(con->packet);
+ free(con);
+ return ERR_PTR(ret);
+}
- if ((ip->ip_hl_v & 0xf0) != 0x40) {
- return;
- }
- if (ip->ip_off & htons(0x1fff)) { /* Can't deal w/ fragments */
- return;
- }
- if (!NetCksumOk((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2)) {
- puts ("checksum bad\n");
- return;
- }
- tmp = NetReadIP(&ip->ip_dst);
- if (NetOurIP && tmp != NetOurIP && tmp != 0xFFFFFFFF) {
- return;
- }
- /*
- * watch for ICMP host redirects
- *
- * There is no real handler code (yet). We just watch
- * for ICMP host redirect messages. In case anybody
- * sees these messages: please contact me
- * (wd@denx.de), or - even better - send me the
- * necessary fixes :-)
- *
- * Note: in all cases where I have seen this so far
- * it was a problem with the router configuration,
- * for instance when a router was configured in the
- * BOOTP reply, but the TFTP server was on the same
- * subnet. So this is probably a warning that your
- * configuration might be wrong. But I'm not really
- * sure if there aren't any other situations.
- */
- if (ip->ip_p == IPPROTO_ICMP) {
- ICMP_t *icmph = (ICMP_t *)&(ip->udp_src);
-
- switch (icmph->type) {
- case ICMP_REDIRECT:
- if (icmph->code != ICMP_REDIR_HOST)
- return;
- puts (" ICMP Host Redirect to ");
- print_IPaddr(icmph->un.gateway);
- putchar(' ');
- return;
-#ifdef CONFIG_NET_PING
- case ICMP_ECHO_REPLY:
- /*
- * IP header OK. Pass the packet to the current handler.
- */
- /* XXX point to ip packet */
- (*packetHandler)((uchar *)ip, 0, 0, 0);
- return;
-#endif
- default:
- return;
- }
- } else if (ip->ip_p != IPPROTO_UDP) { /* Only UDP packets */
- return;
- }
+struct net_connection *net_udp_new(IPaddr_t dest, uint16_t dport,
+ rx_handler_f *handler)
+{
+ struct net_connection *con = net_new(dest, handler);
-#ifdef CONFIG_UDP_CHECKSUM
- if (ip->udp_xsum != 0) {
- ulong xsum;
- ushort *sumptr;
- ushort sumlen;
-
- xsum = ip->ip_p;
- xsum += (ntohs(ip->udp_len));
- xsum += (ntohl(ip->ip_src) >> 16) & 0x0000ffff;
- xsum += (ntohl(ip->ip_src) >> 0) & 0x0000ffff;
- xsum += (ntohl(ip->ip_dst) >> 16) & 0x0000ffff;
- xsum += (ntohl(ip->ip_dst) >> 0) & 0x0000ffff;
-
- sumlen = ntohs(ip->udp_len);
- sumptr = (ushort *) &(ip->udp_src);
-
- while (sumlen > 1) {
- ushort sumdata;
-
- sumdata = *sumptr++;
- xsum += ntohs(sumdata);
- sumlen -= 2;
- }
- if (sumlen > 0) {
- ushort sumdata;
-
- sumdata = *(unsigned char *) sumptr;
- sumdata = (sumdata << 8) & 0xff00;
- xsum += sumdata;
- }
- while ((xsum >> 16) != 0) {
- xsum = (xsum & 0x0000ffff) + ((xsum >> 16) & 0x0000ffff);
- }
- if ((xsum != 0x00000000) && (xsum != 0x0000ffff)) {
- printf(" UDP wrong checksum %08x %08x\n", xsum, ntohs(ip->udp_xsum));
- return;
- }
- }
-#endif
- /*
- * IP header OK. Pass the packet to the current handler.
- */
- (*packetHandler)((uchar *)ip +IP_HDR_SIZE,
- ntohs(ip->udp_dst),
- ntohs(ip->udp_src),
- ntohs(ip->udp_len) - 8);
- break;
- }
-}
+ if (IS_ERR(con))
+ return con;
+ con->proto = IPPROTO_UDP;
+ con->udp->uh_dport = htons(dport);
+ con->udp->uh_sport = htons(net_udp_new_localport());
+ con->ip->protocol = IPPROTO_UDP;
-/**********************************************************************/
+ return con;
+}
-static int net_check_prereq (proto_t protocol)
+struct net_connection *net_icmp_new(IPaddr_t dest, rx_handler_f *handler)
{
- struct eth_device *edev = eth_get_current();
+ struct net_connection *con = net_new(dest, handler);
- switch (protocol) {
- /* Fall through */
-#ifdef CONFIG_NET_NFS
- case NFS:
-#endif
- case NETCONS:
- case TFTP:
- if (NetServerIP == 0) {
- printf("*** ERROR: `%s.serverip' not set\n", dev_id(&edev->dev));
- return -1;
- }
+ if (IS_ERR(con))
+ return con;
- if (NetOurIP == 0) {
- printf("*** ERROR: `%s.ipaddr' not set\n", dev_id(&edev->dev));
- return -1;
- }
- /* Fall through */
-
- case DHCP:
- case RARP:
- case BOOTP:
- if (memcmp (NetOurEther, "\0\0\0\0\0\0", 6) == 0) {
- printf("*** ERROR: `%s.ethaddr' not set\n", dev_id(&edev->dev));
- return -1;
- }
- /* Fall through */
- default:
- return 0;
- }
+ con->proto = IPPROTO_ICMP;
+ con->ip->protocol = IPPROTO_ICMP;
- return -1; /* not reached */
+ return con;
}
-/**********************************************************************/
-int
-NetCksumOk(uchar * ptr, int len)
+void net_unregister(struct net_connection *con)
{
- return !((NetCksum(ptr, len) + 1) & 0xfffe);
+ list_del(&con->list);
+ free(con->packet);
+ free(con);
}
-
-unsigned
-NetCksum(uchar * ptr, int len)
+int net_ip_send(struct net_connection *con, int len)
{
- ulong xsum;
- ushort *p = (ushort *)ptr;
+ con->ip->tot_len = htons(sizeof(struct iphdr) + len);
+ con->ip->id = htons(net_ip_id++);;
+ con->ip->check = 0;
+ con->ip->check = ~net_checksum((unsigned char *)con->ip, sizeof(struct iphdr));
- xsum = 0;
- while (len-- > 0)
- xsum += *p++;
- xsum = (xsum & 0xffff) + (xsum >> 16);
- xsum = (xsum & 0xffff) + (xsum >> 16);
- return xsum & 0xffff;
+ eth_send(con->packet, ETHER_HDR_SIZE + sizeof(struct iphdr) + len);
+
+ return 0;
}
-int
-NetEthHdrSize(void)
+int net_udp_send(struct net_connection *con, int len)
{
- ushort myvlanid;
+ con->udp->uh_ulen = htons(len + 8);
+ con->udp->uh_sum = 0;
- myvlanid = ntohs(NetOurVLAN);
- if (myvlanid == (ushort)-1)
- myvlanid = VLAN_NONE;
-
- return ((myvlanid & VLAN_IDMASK) == VLAN_NONE) ? ETHER_HDR_SIZE : VLAN_ETHER_HDR_SIZE;
+ return net_ip_send(con, sizeof(struct udphdr) + len);
}
-int
-NetSetEther(uchar * xet, uchar * addr, uint prot)
+int net_icmp_send(struct net_connection *con, int len)
{
- Ethernet_t *et = (Ethernet_t *)xet;
- ushort myvlanid;
-
- myvlanid = ntohs(NetOurVLAN);
- if (myvlanid == (ushort)-1)
- myvlanid = VLAN_NONE;
-
- memcpy (et->et_dest, addr, 6);
- memcpy (et->et_src, NetOurEther, 6);
- if ((myvlanid & VLAN_IDMASK) == VLAN_NONE) {
- et->et_protlen = htons(prot);
- return ETHER_HDR_SIZE;
- } else {
- VLAN_Ethernet_t *vet = (VLAN_Ethernet_t *)xet;
+ con->icmp->checksum = ~net_checksum((unsigned char *)con->icmp,
+ sizeof(struct icmphdr) + len);
- vet->vet_vlan_type = htons(PROT_VLAN);
- vet->vet_tag = htons((0 << 5) | (myvlanid & VLAN_IDMASK));
- vet->vet_type = htons(prot);
- return VLAN_ETHER_HDR_SIZE;
- }
+ return net_ip_send(con, sizeof(struct icmphdr) + len);
}
-void
-NetSetIP(uchar * xip, IPaddr_t dest, int dport, int sport, int len)
+static int net_answer_arp(unsigned char *pkt, int len)
{
- IP_t *ip = (IP_t *)xip;
+ struct arprequest *arp = (struct arprequest *)(pkt + ETHER_HDR_SIZE);
+ struct ethernet *et = (struct ethernet *)pkt;
+ unsigned char *packet;
- /*
- * If the data is an odd number of bytes, zero the
- * byte after the last byte so that the checksum
- * will work.
- */
- if (len & 1)
- xip[IP_HDR_SIZE + len] = 0;
+ debug("%s\n", __func__);
- /*
- * Construct an IP and UDP header.
- * (need to set no fragment bit - XXX)
- */
- ip->ip_hl_v = 0x45; /* IP_HDR_SIZE / 4 (not including UDP) */
- ip->ip_tos = 0;
- ip->ip_len = htons(IP_HDR_SIZE + len);
- ip->ip_id = htons(NetIPID++);
- ip->ip_off = htons(0x4000); /* No fragmentation */
- ip->ip_ttl = 255;
- ip->ip_p = 17; /* UDP */
- ip->ip_sum = 0;
- NetCopyIP((void*)&ip->ip_src, &NetOurIP); /* already in network byte order */
- NetCopyIP((void*)&ip->ip_dst, &dest); /* - "" - */
- ip->udp_src = htons(sport);
- ip->udp_dst = htons(dport);
- ip->udp_len = htons(8 + len);
- ip->udp_xsum = 0;
- ip->ip_sum = ~NetCksum((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2);
+ memcpy (et->et_dest, et->et_src, 6);
+ memcpy (et->et_src, net_ether, 6);
+
+ et->et_protlen = htons(PROT_ARP);
+ arp->ar_op = htons(ARPOP_REPLY);
+ memcpy(&arp->ar_data[10], &arp->ar_data[0], 6);
+ net_copy_ip(&arp->ar_data[16], &arp->ar_data[6]);
+ memcpy(&arp->ar_data[0], net_ether, 6);
+ net_copy_ip(&arp->ar_data[6], &net_ip);
+
+ packet = net_alloc_packet();
+ if (!packet)
+ return 0;
+ memcpy(packet, pkt, ETHER_HDR_SIZE + ARP_HDR_SIZE);
+ eth_send(packet, ETHER_HDR_SIZE + ARP_HDR_SIZE);
+ free(packet);
+
+ return 0;
}
-char *ip_to_string (IPaddr_t x, char *s)
+static void net_bad_packet(unsigned char *pkt, int len)
{
- x = ntohl (x);
- sprintf (s, "%d.%d.%d.%d",
- (int) ((x >> 24) & 0xff),
- (int) ((x >> 16) & 0xff),
- (int) ((x >> 8) & 0xff), (int) ((x >> 0) & 0xff)
- );
- return s;
+#ifdef DEBUG
+ /*
+ * We received a bad packet. for now just dump it.
+ * We could add more sophisticated debugging here
+ */
+ memory_display(pkt, 0, len, 1);
+#endif
}
-int string_to_ip(const char *s, IPaddr_t *ip)
+static int net_handle_arp(unsigned char *pkt, int len)
{
- IPaddr_t addr = 0;
- char *e;
- int i;
+ struct arprequest *arp;
- if (!s)
- return -EINVAL;
+ debug("%s: got arp\n", __func__);
- for (i = 0; i < 4; i++) {
- ulong val;
+ /*
+ * We have to deal with two types of ARP packets:
+ * - REQUEST packets will be answered by sending our
+ * IP address - if we know it.
+ * - REPLY packets are expected only after we asked
+ * for the TFTP server's or the gateway's ethernet
+ * address; so if we receive such a packet, we set
+ * the server ethernet address
+ */
+ arp = (struct arprequest *)(pkt + ETHER_HDR_SIZE);
+ if (len < ARP_HDR_SIZE)
+ goto bad;
+ if (ntohs(arp->ar_hrd) != ARP_ETHER)
+ goto bad;
+ if (ntohs(arp->ar_pro) != PROT_IP)
+ goto bad;
+ if (arp->ar_hln != 6)
+ goto bad;
+ if (arp->ar_pln != 4)
+ goto bad;
+ if (net_ip == 0)
+ return 0;
+ if (net_read_ip(&arp->ar_data[16]) != net_ip)
+ return 0;
- if (!isdigit(*s))
- return -EINVAL;
+ switch (ntohs(arp->ar_op)) {
+ case ARPOP_REQUEST:
+ return net_answer_arp(pkt, len);
+ case ARPOP_REPLY:
+ arp_handler(arp);
+ return 1;
+ default:
+ pr_debug("Unexpected ARP opcode 0x%x\n", ntohs(arp->ar_op));
+ return -EINVAL;
+ }
- val = simple_strtoul(s, &e, 10);
- addr <<= 8;
- addr |= (val & 0xFF);
+ return 0;
- if (*e != '.' && i != 3)
- return -EINVAL;
+bad:
+ net_bad_packet(pkt, len);
+ return -EINVAL;
+}
- s = e + 1;
+static int net_handle_udp(unsigned char *pkt, int len)
+{
+ struct iphdr *ip = (struct iphdr *)(pkt + ETHER_HDR_SIZE);
+ struct net_connection *con;
+ struct udphdr *udp;
+ int port;
+
+ udp = (struct udphdr *)(ip + 1);
+ port = ntohs(udp->uh_dport);
+ list_for_each_entry(con, &connection_list, list) {
+ if (con->proto == IPPROTO_UDP && port == ntohs(con->udp->uh_sport)) {
+ con->handler(pkt, len);
+ return 0;
+ }
}
-
- *ip = htonl(addr);
- return 0;
+ return -EINVAL;
}
-void VLAN_to_string(ushort x, char *s)
+static int net_handle_icmp(unsigned char *pkt, int len)
{
- x = ntohs(x);
+ struct net_connection *con;
- if (x == (ushort)-1)
- x = VLAN_NONE;
+ debug("%s\n", __func__);
- if (x == VLAN_NONE)
- strcpy(s, "none");
- else
- sprintf(s, "%d", x & VLAN_IDMASK);
+ list_for_each_entry(con, &connection_list, list) {
+ if (con->proto == IPPROTO_ICMP) {
+ con->handler(pkt, len);
+ return 0;
+ }
+ }
+ return 0;
}
-ushort string_to_VLAN(const char *s)
+static int net_handle_ip(unsigned char *pkt, int len)
{
- ushort id;
+ struct iphdr *ip = (struct iphdr *)(pkt + ETHER_HDR_SIZE);
+ IPaddr_t tmp;
- if (s == NULL)
- return htons(VLAN_NONE);
+ debug("%s\n", __func__);
- if (*s < '0' || *s > '9')
- id = VLAN_NONE;
- else
- id = (ushort)simple_strtoul(s, NULL, 10);
+ if (len < sizeof(struct ethernet) + sizeof(struct iphdr) ||
+ len < ETHER_HDR_SIZE + ntohs(ip->tot_len)) {
+ debug("%s: bad len\n", __func__);
+ goto bad;
+ }
- return htons(id);
-}
+ if ((ip->hl_v & 0xf0) != 0x40)
+ goto bad;
-void print_IPaddr (IPaddr_t x)
-{
- char tmp[16];
+ if (ip->frag_off & htons(0x1fff)) /* Can't deal w/ fragments */
+ goto bad;
+ if (!net_checksum_ok((unsigned char *)ip, sizeof(struct iphdr)))
+ goto bad;
- ip_to_string (x, tmp);
+ tmp = net_read_ip(&ip->daddr);
+ if (net_ip && tmp != net_ip && tmp != 0xffffffff)
+ return 0;
- puts (tmp);
-}
+ switch (ip->protocol) {
+ case IPPROTO_ICMP:
+ return net_handle_icmp(pkt, len);
+ case IPPROTO_UDP:
+ return net_handle_udp(pkt, len);
+ }
-ushort getenv_VLAN(char *var)
-{
- return string_to_VLAN(getenv(var));
+ return 0;
+bad:
+ net_bad_packet(pkt, len);
+ return 0;
}
-int string_to_ethaddr(const char *str, char *enetaddr)
+int net_receive(unsigned char *pkt, int len)
{
- ulong reg;
- char *e;
+ struct ethernet *et = (struct ethernet *)pkt;
+ int et_protlen = ntohs(et->et_protlen);
- if (!str || strlen(str) != 17)
- return -1;
-
- if (str[2] != ':' || str[5] != ':' || str[8] != ':' ||
- str[11] != ':' || str[14] != ':')
- return -1;
+ if (len < ETHER_HDR_SIZE)
+ return 0;
- for (reg = 0; reg < 6; ++reg) {
- enetaddr[reg] = simple_strtoul (str, &e, 16);
- str = e + 1;
+ switch (et_protlen) {
+ case PROT_ARP:
+ return net_handle_arp(pkt, len);
+ case PROT_IP:
+ return net_handle_ip(pkt, len);
+ default:
+ debug("%s: got unknown protocol type: %d\n", __func__, et_protlen);
+ return 1;
}
-
- return 0;
}
-void ethaddr_to_string(const unsigned char *enetaddr, char *str)
+static int net_init(void)
{
- sprintf (str, "%02X:%02X:%02X:%02X:%02X:%02X",
- enetaddr[0], enetaddr[1], enetaddr[2], enetaddr[3],
- enetaddr[4], enetaddr[5]);
+ int i;
+
+ for (i = 0; i < PKTBUFSRX; i++)
+ NetRxPackets[i] = memalign(32, PKTSIZE);
+
+ return 0;
}
+postcore_initcall(net_init);
+
diff --git a/net/netconsole.c b/net/netconsole.c
new file mode 100644
index 0000000000..07e6a6cf27
--- /dev/null
+++ b/net/netconsole.c
@@ -0,0 +1,228 @@
+/*
+ * netconsole.c - network console support
+ *
+ * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * 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 version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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>
+#include <command.h>
+#include <fs.h>
+#include <linux/stat.h>
+#include <errno.h>
+#include <malloc.h>
+#include <getopt.h>
+#include <stringlist.h>
+#include <net.h>
+#include <kfifo.h>
+#include <init.h>
+#include <linux/err.h>
+
+/**
+ * @file
+ * @brief Network console support
+ */
+
+struct nc_priv {
+ struct console_device cdev;
+ struct kfifo *fifo;
+ int busy;
+ struct net_connection *con;
+
+ uint16_t port;
+ IPaddr_t ip;
+};
+
+static struct nc_priv *g_priv;
+
+static void nc_handler(char *pkt, unsigned len)
+{
+ struct nc_priv *priv = g_priv;
+ unsigned char *packet = net_eth_to_udp_payload(pkt);
+
+ kfifo_put(priv->fifo, packet, net_eth_to_udplen(pkt));
+}
+
+static int nc_init(void)
+{
+ struct nc_priv *priv = g_priv;
+
+ if (priv->con)
+ net_unregister(priv->con);
+
+ priv->con = net_udp_new(priv->ip, priv->port, nc_handler);
+ if (IS_ERR(priv->con)) {
+ int ret = PTR_ERR(priv->con);
+ priv->con = NULL;
+ return ret;
+ }
+
+ net_udp_bind(priv->con, priv->port);
+ priv->cdev.f_caps = CONSOLE_STDIN | CONSOLE_STDOUT | CONSOLE_STDERR;
+ return 0;
+}
+
+static int nc_getc(struct console_device *cdev)
+{
+ struct nc_priv *priv = container_of(cdev,
+ struct nc_priv, cdev);
+ unsigned char c;
+
+ while (!kfifo_len(priv->fifo))
+ net_poll();
+
+ kfifo_getc(priv->fifo, &c);
+
+ return c;
+}
+
+static int nc_tstc(struct console_device *cdev)
+{
+ struct nc_priv *priv = container_of(cdev,
+ struct nc_priv, cdev);
+
+ if (priv->busy)
+ return kfifo_len(priv->fifo) ? 1 : 0;
+
+ net_poll();
+
+ return kfifo_len(priv->fifo) ? 1 : 0;
+}
+
+static void nc_putc(struct console_device *cdev, char c)
+{
+ struct nc_priv *priv = container_of(cdev,
+ struct nc_priv, cdev);
+ unsigned char *packet;
+
+ if (!priv->con)
+ return;
+
+ if (priv->busy)
+ return;
+
+ packet = net_udp_get_payload(priv->con);
+ *packet = c;
+
+ priv->busy = 1;
+ net_udp_send(priv->con, 1);
+ priv->busy = 0;
+}
+
+static int nc_setbaudrate(struct console_device *cdev, int baudrate)
+{
+ return 0;
+}
+
+static int nc_port_set(struct device_d *dev, struct param_d *param,
+ const char *val)
+{
+ struct nc_priv *priv = g_priv;
+ char portstr[16];
+ int port;
+
+ if (!val)
+ dev_param_set_generic(dev, param, NULL);
+
+ port = simple_strtoul(val, NULL, 10);
+ if (port > 65535)
+ return -EINVAL;
+
+ priv->port = port;
+ nc_init();
+
+ sprintf(portstr, "%d", port);
+ dev_param_set_generic(dev, param, portstr);
+
+ return 0;
+}
+
+static int nc_remoteip_set(struct device_d *dev, struct param_d *param,
+ const char *val)
+{
+ struct nc_priv *priv = g_priv;
+ IPaddr_t ip;
+ int ret;
+
+ if (!val)
+ dev_param_set_generic(dev, param, NULL);
+
+ if (string_to_ip(val, &ip))
+ return -EINVAL;
+
+ priv->ip = ip;
+ ret = nc_init();
+ if (ret)
+ return ret;
+
+ dev_param_set_generic(dev, param, val);
+
+ return 0;
+}
+
+static int netconsole_init(void)
+{
+ struct nc_priv *priv;
+ struct console_device *cdev;
+
+ priv = xzalloc(sizeof(*priv));
+ cdev = &priv->cdev;
+ cdev->tstc = nc_tstc;
+ cdev->putc = nc_putc;
+ cdev->getc = nc_getc;
+ cdev->setbrg = nc_setbaudrate;
+
+ g_priv = priv;
+
+ priv->fifo = kfifo_alloc(1024);
+
+ console_register(cdev);
+
+ dev_add_param(&cdev->class_dev, "ip", nc_remoteip_set, NULL, 0);
+ dev_add_param(&cdev->class_dev, "port", nc_port_set, NULL, 0);
+ dev_set_param(&cdev->class_dev, "port", "6666");
+
+ printf("registered netconsole as %s%d\n", cdev->class_dev.name, cdev->class_dev.id);
+
+ return 0;
+}
+
+device_initcall(netconsole_init);
+
+/** @page net_netconsole Network console
+
+@section net_netconsole Using an UDP based network console
+
+If enabled barebox supports a console via udp networking. There is only
+one network console supported registered during init time. It is deactivated
+by default because it opens great security holes, so use with care.
+
+To use the network console you have to configure the remote ip and the local
+and remote ports. Assuming the network console is registered as cs1, it can be
+configured with:
+
+@code
+cs1.ip=<remotehost>
+cs1.port=<port>
+cs1.active=ioe
+@endcode
+
+On the remote host call scripts/netconsole with bareboxes ip and port as
+parameters. port is initialized to 6666 by default.
+
+*/
diff --git a/net/nfs.c b/net/nfs.c
index 15f91abc48..51df7a367c 100644
--- a/net/nfs.c
+++ b/net/nfs.c
@@ -32,28 +32,111 @@
#include <libgen.h>
#include <fcntl.h>
#include <errno.h>
-#include "nfs.h"
-
-/*#define NFS_DEBUG*/
+#include <linux/err.h>
+
+#define SUNRPC_PORT 111
+
+#define PROG_PORTMAP 100000
+#define PROG_NFS 100003
+#define PROG_MOUNT 100005
+
+#define MSG_CALL 0
+#define MSG_REPLY 1
+
+#define PORTMAP_GETPORT 3
+
+#define MOUNT_ADDENTRY 1
+#define MOUNT_UMOUNTALL 4
+
+#define NFS_LOOKUP 4
+#define NFS_READLINK 5
+#define NFS_READ 6
+
+#define NFS_FHSIZE 32
+
+enum nfs_stat {
+ NFS_OK = 0,
+ NFSERR_PERM = 1,
+ NFSERR_NOENT = 2,
+ NFSERR_IO = 5,
+ NFSERR_NXIO = 6,
+ NFSERR_ACCES = 13,
+ NFSERR_EXIST = 17,
+ NFSERR_NODEV = 19,
+ NFSERR_NOTDIR = 20,
+ NFSERR_ISDIR = 21,
+ NFSERR_FBIG = 27,
+ NFSERR_NOSPC = 28,
+ NFSERR_ROFS = 30,
+ NFSERR_NAMETOOLONG=63,
+ NFSERR_NOTEMPTY = 66,
+ NFSERR_DQUOT = 69,
+ NFSERR_STALE = 70,
+ NFSERR_WFLUSH = 99,
+};
+
+/* Block size used for NFS read accesses. A RPC reply packet (including all
+ * headers) must fit within a single Ethernet frame to avoid fragmentation.
+ * Chosen to be a power of two, as most NFS servers are optimized for this. */
+#define NFS_READ_SIZE 1024
+
+struct rpc_call {
+ uint32_t id;
+ uint32_t type;
+ uint32_t rpcvers;
+ uint32_t prog;
+ uint32_t vers;
+ uint32_t proc;
+ uint32_t data[0];
+};
+
+struct rpc_reply {
+ uint32_t id;
+ uint32_t type;
+ uint32_t rstatus;
+ uint32_t verifier;
+ uint32_t v2;
+ uint32_t astatus;
+ uint32_t data[0];
+};
+
+struct rpc_t {
+ union {
+ struct {
+ uint32_t id;
+ uint32_t type;
+ uint32_t rpcvers;
+ uint32_t prog;
+ uint32_t vers;
+ uint32_t proc;
+ uint32_t data[1];
+ } call;
+ struct {
+ uint32_t id;
+ uint32_t type;
+ uint32_t rstatus;
+ uint32_t verifier;
+ uint32_t v2;
+ uint32_t astatus;
+ uint32_t data[19];
+ } reply;
+ } u;
+};
#define HASHES_PER_LINE 65 /* Number of "loading" hashes per line */
#define NFS_TIMEOUT 60
-static int fs_mounted = 0;
static unsigned long rpc_id = 0;
static int nfs_offset = -1;
-static int nfs_len;
+static uint64_t nfs_timer_start;
+static int nfs_err;
static char dirfh[NFS_FHSIZE]; /* file handle of directory */
static char filefh[NFS_FHSIZE]; /* file handle of kernel image */
-static int NfsDownloadState;
-static IPaddr_t NfsServerIP;
-static int NfsSrvMountPort;
-static int NfsSrvNfsPort;
-static int NfsOurPort;
-static int NfsTimeoutCount;
-static int NfsState;
+static int nfs_server_mount_port;
+static int nfs_server_nfs_port;
+static int nfs_state;
#define STATE_PRCLOOKUP_PROG_MOUNT_REQ 1
#define STATE_PRCLOOKUP_PROG_NFS_REQ 2
#define STATE_MOUNT_REQ 3
@@ -61,40 +144,22 @@ static int NfsState;
#define STATE_LOOKUP_REQ 5
#define STATE_READ_REQ 6
#define STATE_READLINK_REQ 7
+#define STATE_DONE 8
static char *nfs_filename;
static char *nfs_path;
static char nfs_path_buff[2048];
static int net_store_fd;
-
-static __inline__ int
-store_block (uchar * src, unsigned offset, unsigned len)
-{
- ulong newsize = offset + len;
- int ret;
-
- ret = write(net_store_fd, src, len);
- if (ret < 0)
- return ret;
-
- if (NetBootFileXferSize < (offset+len))
- NetBootFileXferSize = newsize;
-
- return 0;
-}
+static struct net_connection *nfs_con;
/**************************************************************************
RPC_ADD_CREDENTIALS - Add RPC authentication/verifier entries
**************************************************************************/
-static long *rpc_add_credentials (long *p)
+static uint32_t *rpc_add_credentials(uint32_t *p)
{
int hl;
- int hostnamelen;
- char hostname[256];
-
- strcpy (hostname, "");
- hostnamelen=strlen (hostname);
+ int hostnamelen = 0;
/* Here's the executive summary on authentication requirements of the
* various NFS server implementations: Linux accepts both AUTH_NONE
@@ -112,10 +177,12 @@ static long *rpc_add_credentials (long *p)
*p++ = htonl(hl+20); /* auth length */
*p++ = htonl(0); /* stamp */
*p++ = htonl(hostnamelen); /* hostname string */
- if (hostnamelen & 3) {
+
+ if (hostnamelen & 3)
*(p + hostnamelen / 4) = 0; /* add zero padding */
- }
- memcpy (p, hostname, hostnamelen);
+
+ /* memcpy(p, hostname, hostnamelen); */ /* empty hostname */
+
p += hl / 4;
*p++ = 0; /* uid */
*p++ = 0; /* gid */
@@ -131,46 +198,42 @@ static long *rpc_add_credentials (long *p)
/**************************************************************************
RPC_LOOKUP - Lookup RPC Port numbers
**************************************************************************/
-static void
-rpc_req (int rpc_prog, int rpc_proc, uint32_t *data, int datalen)
+static int rpc_req(int rpc_prog, int rpc_proc, uint32_t *data, int datalen)
{
- struct rpc_t pkt;
+ struct rpc_call pkt;
unsigned long id;
- uint32_t *p;
- int pktlen;
int sport;
+ int ret;
+ unsigned char *payload = net_udp_get_payload(nfs_con);
id = ++rpc_id;
- pkt.u.call.id = htonl(id);
- pkt.u.call.type = htonl(MSG_CALL);
- pkt.u.call.rpcvers = htonl(2); /* use RPC version 2 */
- pkt.u.call.prog = htonl(rpc_prog);
- pkt.u.call.vers = htonl(2); /* portmapper is version 2 */
- pkt.u.call.proc = htonl(rpc_proc);
- p = (uint32_t *)&(pkt.u.call.data);
-
- if (datalen)
- memcpy ((char *)p, (char *)data, datalen*sizeof(uint32_t));
-
- pktlen = (char *)p + datalen*sizeof(uint32_t) - (char *)&pkt;
+ pkt.id = htonl(id);
+ pkt.type = htonl(MSG_CALL);
+ pkt.rpcvers = htonl(2); /* use RPC version 2 */
+ pkt.prog = htonl(rpc_prog);
+ pkt.vers = htonl(2); /* portmapper is version 2 */
+ pkt.proc = htonl(rpc_proc);
- memcpy ((char *)NetTxPacket + NetEthHdrSize() + IP_HDR_SIZE, (char *)&pkt, pktlen);
+ memcpy(payload, &pkt, sizeof(pkt));
+ memcpy(payload + sizeof(pkt), data, datalen * sizeof(uint32_t));
if (rpc_prog == PROG_PORTMAP)
sport = SUNRPC_PORT;
else if (rpc_prog == PROG_MOUNT)
- sport = NfsSrvMountPort;
+ sport = nfs_server_mount_port;
else
- sport = NfsSrvNfsPort;
+ sport = nfs_server_nfs_port;
- NetSendUDPPacket (NetServerEther, NfsServerIP, sport, NfsOurPort, pktlen);
+ nfs_con->udp->uh_dport = htons(sport);
+ ret = net_udp_send(nfs_con, sizeof(pkt) + datalen * sizeof(uint32_t));
+
+ return ret;
}
/**************************************************************************
RPC_LOOKUP - Lookup RPC Port numbers
**************************************************************************/
-static void
-rpc_lookup_req (int prog, int ver)
+static void rpc_lookup_req(int prog, int ver)
{
uint32_t data[16];
@@ -181,14 +244,13 @@ rpc_lookup_req (int prog, int ver)
data[6] = htonl(17); /* IP_UDP */
data[7] = 0;
- rpc_req (PROG_PORTMAP, PORTMAP_GETPORT, data, 8);
+ rpc_req(PROG_PORTMAP, PORTMAP_GETPORT, data, 8);
}
/**************************************************************************
NFS_MOUNT - Mount an NFS Filesystem
**************************************************************************/
-static void
-nfs_mount_req (char *path)
+static void nfs_mount_req(char *path)
{
uint32_t data[1024];
uint32_t *p;
@@ -198,39 +260,38 @@ nfs_mount_req (char *path)
pathlen = strlen (path);
p = &(data[0]);
- p = (uint32_t *)rpc_add_credentials((long *)p);
+ p = rpc_add_credentials(p);
*p++ = htonl(pathlen);
- if (pathlen & 3) *(p + pathlen / 4) = 0;
+ if (pathlen & 3)
+ *(p + pathlen / 4) = 0;
memcpy (p, path, pathlen);
p += (pathlen + 3) / 4;
- len = (uint32_t *)p - (uint32_t *)&(data[0]);
+ len = p - &(data[0]);
- rpc_req (PROG_MOUNT, MOUNT_ADDENTRY, data, len);
+ rpc_req(PROG_MOUNT, MOUNT_ADDENTRY, data, len);
}
/**************************************************************************
NFS_UMOUNTALL - Unmount all our NFS Filesystems on the Server
**************************************************************************/
-static void
-nfs_umountall_req (void)
+static void nfs_umountall_req(void)
{
uint32_t data[1024];
uint32_t *p;
int len;
- if ((NfsSrvMountPort == -1) || (!fs_mounted)) {
+ if (nfs_server_mount_port < 0)
/* Nothing mounted, nothing to umount */
return;
- }
p = &(data[0]);
- p = (uint32_t *)rpc_add_credentials ((long *)p);
+ p = rpc_add_credentials(p);
- len = (uint32_t *)p - (uint32_t *)&(data[0]);
+ len = p - &(data[0]);
- rpc_req (PROG_MOUNT, MOUNT_UMOUNTALL, data, len);
+ rpc_req(PROG_MOUNT, MOUNT_UMOUNTALL, data, len);
}
/***************************************************************************
@@ -240,29 +301,27 @@ nfs_umountall_req (void)
* In case of successful readlink(), the dirname is manipulated,
* so that inside the nfs() function a recursion can be done.
**************************************************************************/
-static void
-nfs_readlink_req (void)
+static void nfs_readlink_req(void)
{
uint32_t data[1024];
uint32_t *p;
int len;
p = &(data[0]);
- p = (uint32_t *)rpc_add_credentials ((long *)p);
+ p = rpc_add_credentials(p);
memcpy (p, filefh, NFS_FHSIZE);
p += (NFS_FHSIZE / 4);
- len = (uint32_t *)p - (uint32_t *)&(data[0]);
+ len = p - &(data[0]);
- rpc_req (PROG_NFS, NFS_READLINK, data, len);
+ rpc_req(PROG_NFS, NFS_READLINK, data, len);
}
/**************************************************************************
NFS_LOOKUP - Lookup Pathname
**************************************************************************/
-static void
-nfs_lookup_req (char *fname)
+static void nfs_lookup_req(char *fname)
{
uint32_t data[1024];
uint32_t *p;
@@ -272,32 +331,32 @@ nfs_lookup_req (char *fname)
fnamelen = strlen (fname);
p = &(data[0]);
- p = (uint32_t *)rpc_add_credentials ((long *)p);
+ p = rpc_add_credentials(p);
memcpy (p, dirfh, NFS_FHSIZE);
p += (NFS_FHSIZE / 4);
*p++ = htonl(fnamelen);
- if (fnamelen & 3) *(p + fnamelen / 4) = 0;
+ if (fnamelen & 3)
+ *(p + fnamelen / 4) = 0;
memcpy (p, fname, fnamelen);
p += (fnamelen + 3) / 4;
- len = (uint32_t *)p - (uint32_t *)&(data[0]);
+ len = p - &(data[0]);
- rpc_req (PROG_NFS, NFS_LOOKUP, data, len);
+ rpc_req(PROG_NFS, NFS_LOOKUP, data, len);
}
/**************************************************************************
NFS_READ - Read File on NFS Server
**************************************************************************/
-static void
-nfs_read_req (int offset, int readlen)
+static void nfs_read_req(int offset, int readlen)
{
uint32_t data[1024];
uint32_t *p;
int len;
p = &(data[0]);
- p = (uint32_t *)rpc_add_credentials ((long *)p);
+ p = rpc_add_credentials(p);
memcpy (p, filefh, NFS_FHSIZE);
p += (NFS_FHSIZE / 4);
@@ -305,238 +364,194 @@ nfs_read_req (int offset, int readlen)
*p++ = htonl(readlen);
*p++ = 0;
- len = (uint32_t *)p - (uint32_t *)&(data[0]);
+ len = p - &(data[0]);
- rpc_req (PROG_NFS, NFS_READ, data, len);
+ rpc_req(PROG_NFS, NFS_READ, data, len);
}
/**************************************************************************
RPC request dispatcher
**************************************************************************/
-
-static void
-NfsSend (void)
+static void nfs_send(void)
{
-#ifdef NFS_DEBUG
- printf ("%s\n", __FUNCTION__);
-#endif
+ debug("%s\n", __func__);
- switch (NfsState) {
+ switch (nfs_state) {
case STATE_PRCLOOKUP_PROG_MOUNT_REQ:
- rpc_lookup_req (PROG_MOUNT, 1);
+ rpc_lookup_req(PROG_MOUNT, 1);
break;
case STATE_PRCLOOKUP_PROG_NFS_REQ:
- rpc_lookup_req (PROG_NFS, 2);
+ rpc_lookup_req(PROG_NFS, 2);
break;
case STATE_MOUNT_REQ:
- nfs_mount_req (nfs_path);
+ nfs_mount_req(nfs_path);
break;
case STATE_UMOUNT_REQ:
- nfs_umountall_req ();
+ nfs_umountall_req();
break;
case STATE_LOOKUP_REQ:
- nfs_lookup_req (nfs_filename);
+ nfs_lookup_req(nfs_filename);
break;
case STATE_READ_REQ:
- nfs_read_req (nfs_offset, nfs_len);
+ nfs_read_req(nfs_offset, NFS_READ_SIZE);
break;
case STATE_READLINK_REQ:
- nfs_readlink_req ();
+ nfs_readlink_req();
break;
}
}
-/**************************************************************************
-Handlers for the reply from server
-**************************************************************************/
-
-static int
-rpc_lookup_reply (int prog, uchar *pkt, unsigned len)
+static int rpc_check_reply(unsigned char *pkt, int isnfs)
{
- struct rpc_t rpc_pkt;
-
- memcpy ((unsigned char *)&rpc_pkt, pkt, len);
+ uint32_t *data;
+ int nfserr;
+ struct rpc_reply rpc;
-#ifdef NFS_DEBUG
- printf ("%s\n", __FUNCTION__);
-#endif
+ memcpy(&rpc, pkt, sizeof(rpc));
- if (ntohl(rpc_pkt.u.reply.id) != rpc_id)
- return -1;
+ if (ntohl(rpc.id) != rpc_id)
+ return -EINVAL;
- if (rpc_pkt.u.reply.rstatus ||
- rpc_pkt.u.reply.verifier ||
- rpc_pkt.u.reply.astatus ||
- rpc_pkt.u.reply.astatus) {
- return -1;
+ if (rpc.rstatus ||
+ rpc.verifier ||
+ rpc.astatus ) {
+ return -EINVAL;
}
+ if (!isnfs)
+ return 0;
+
+ data = (uint32_t *)(pkt + sizeof(struct rpc_reply));
+ nfserr = ntohl(net_read_uint32(data));
+
+ debug("%s: state: %d, err %d\n", __func__, nfs_state, -nfserr);
+
+ if (nfserr <= 30)
+ /* These nfs codes correspond with those in errno.h */
+ return -nfserr;
+ if (nfserr == NFSERR_STALE)
+ return -ESTALE;
+
+ return -EINVAL;
+}
+
+static int rpc_lookup_reply(int prog, unsigned char *pkt, unsigned len)
+{
+ uint32_t port;
+ int ret;
+
+ ret = rpc_check_reply(pkt, 0);
+ if (ret)
+ return ret;
+
+ port = net_read_uint32((uint32_t *)(pkt + sizeof(struct rpc_reply)));
switch (prog) {
case PROG_MOUNT:
- NfsSrvMountPort = ntohl(rpc_pkt.u.reply.data[0]);
+ nfs_server_mount_port = ntohl(port);
break;
case PROG_NFS:
- NfsSrvNfsPort = ntohl(rpc_pkt.u.reply.data[0]);
+ nfs_server_nfs_port = ntohl(port);
break;
}
return 0;
}
-static int
-nfs_mount_reply (uchar *pkt, unsigned len)
+static int nfs_mount_reply(unsigned char *pkt, unsigned len)
{
- struct rpc_t rpc_pkt;
-
-#ifdef NFS_DEBUG
- printf ("%s\n", __FUNCTION__);
-#endif
-
- memcpy ((unsigned char *)&rpc_pkt, pkt, len);
-
- if (ntohl(rpc_pkt.u.reply.id) != rpc_id)
- return -1;
+ int ret;
- if (rpc_pkt.u.reply.rstatus ||
- rpc_pkt.u.reply.verifier ||
- rpc_pkt.u.reply.astatus ||
- rpc_pkt.u.reply.data[0]) {
- return -1;
- }
+ ret = rpc_check_reply(pkt, 1);
+ if (ret)
+ return ret;
- fs_mounted = 1;
- memcpy (dirfh, rpc_pkt.u.reply.data + 1, NFS_FHSIZE);
+ memcpy(dirfh, pkt + sizeof(struct rpc_reply) + 4, NFS_FHSIZE);
return 0;
}
-static int
-nfs_umountall_reply (uchar *pkt, unsigned len)
+static int nfs_umountall_reply(unsigned char *pkt, unsigned len)
{
- struct rpc_t rpc_pkt;
-
-#ifdef NFS_DEBUG
- printf ("%s\n", __FUNCTION__);
-#endif
-
- memcpy ((unsigned char *)&rpc_pkt, pkt, len);
-
- if (ntohl(rpc_pkt.u.reply.id) != rpc_id)
- return -1;
+ int ret;
- if (rpc_pkt.u.reply.rstatus ||
- rpc_pkt.u.reply.verifier ||
- rpc_pkt.u.reply.astatus) {
- return -1;
- }
+ ret = rpc_check_reply(pkt, 0);
+ if (ret)
+ return ret;
- fs_mounted = 0;
- memset (dirfh, 0, sizeof(dirfh));
+ memset(dirfh, 0, sizeof(dirfh));
return 0;
}
-static int
-nfs_lookup_reply (uchar *pkt, unsigned len)
+static int nfs_lookup_reply(unsigned char *pkt, unsigned len)
{
- struct rpc_t rpc_pkt;
-
-#ifdef NFS_DEBUG
- printf ("%s\n", __FUNCTION__);
-#endif
-
- memcpy ((unsigned char *)&rpc_pkt, pkt, len);
-
- if (ntohl(rpc_pkt.u.reply.id) != rpc_id)
- return -1;
+ int ret;
- if (rpc_pkt.u.reply.rstatus ||
- rpc_pkt.u.reply.verifier ||
- rpc_pkt.u.reply.astatus ||
- rpc_pkt.u.reply.data[0]) {
- return -1;
- }
+ ret = rpc_check_reply(pkt, 1);
+ if (ret)
+ return ret;
- memcpy (filefh, rpc_pkt.u.reply.data + 1, NFS_FHSIZE);
+ memcpy(filefh, pkt + sizeof(struct rpc_reply) + 4, NFS_FHSIZE);
return 0;
}
-static int
-nfs_readlink_reply (uchar *pkt, unsigned len)
+static int nfs_readlink_reply(unsigned char *pkt, unsigned len)
{
- struct rpc_t rpc_pkt;
+ uint32_t *data;
+ char *path;
int rlen;
+ int ret;
-#ifdef NFS_DEBUG
- printf ("%s\n", __FUNCTION__);
-#endif
+ ret = rpc_check_reply(pkt, 1);
+ if (ret)
+ return ret;
- memcpy ((unsigned char *)&rpc_pkt, pkt, len);
+ data = (uint32_t *)(pkt + sizeof(struct rpc_reply));
- if (ntohl(rpc_pkt.u.reply.id) != rpc_id)
- return -1;
+ data++;
- if (rpc_pkt.u.reply.rstatus ||
- rpc_pkt.u.reply.verifier ||
- rpc_pkt.u.reply.astatus ||
- rpc_pkt.u.reply.data[0]) {
- return -1;
- }
+ rlen = ntohl(net_read_uint32(data)); /* new path length */
- rlen = ntohl (rpc_pkt.u.reply.data[1]); /* new path length */
+ data++;
+ path = (char *)data;
- if (*((char *)&(rpc_pkt.u.reply.data[2])) != '/') {
- int pathlen;
- strcat (nfs_path, "/");
- pathlen = strlen(nfs_path);
- memcpy (nfs_path+pathlen, (uchar *)&(rpc_pkt.u.reply.data[2]), rlen);
- nfs_path[pathlen+rlen+1] = 0;
+ if (*path != '/') {
+ strcat(nfs_path, "/");
+ strncat(nfs_path, path, rlen);
} else {
- memcpy (nfs_path, (uchar *)&(rpc_pkt.u.reply.data[2]), rlen);
+ memcpy(nfs_path, path, rlen);
nfs_path[rlen] = 0;
}
return 0;
}
-static int
-nfs_read_reply (uchar *pkt, unsigned len)
+static int nfs_read_reply(unsigned char *pkt, unsigned len)
{
- struct rpc_t rpc_pkt;
int rlen;
+ uint32_t *data;
+ int ret;
-#ifdef NFS_DEBUG_nop
- printf ("%s\n", __FUNCTION__);
-#endif
-
- memcpy ((uchar *)&rpc_pkt, pkt, sizeof(rpc_pkt.u.reply));
+ debug("%s\n", __func__);
- if (ntohl(rpc_pkt.u.reply.id) != rpc_id)
- return -1;
+ ret = rpc_check_reply(pkt, 1);
+ if (ret)
+ return ret;
- if (rpc_pkt.u.reply.rstatus ||
- rpc_pkt.u.reply.verifier ||
- rpc_pkt.u.reply.astatus ||
- rpc_pkt.u.reply.data[0]) {
- if (rpc_pkt.u.reply.rstatus) {
- return -9999;
- }
- if (rpc_pkt.u.reply.astatus) {
- return -9999;
- }
- return -ntohl(rpc_pkt.u.reply.data[0]);;
- }
+ data = (uint32_t *)(pkt + sizeof(struct rpc_reply));
- if ((nfs_offset!=0) && !((nfs_offset) % (NFS_READ_SIZE/2*10*HASHES_PER_LINE))) {
+ if (nfs_offset && !((nfs_offset) % (NFS_READ_SIZE / 2 * 10 * HASHES_PER_LINE)))
puts ("\n\t ");
- }
- if (!(nfs_offset % ((NFS_READ_SIZE/2)*10))) {
+ if (!(nfs_offset % ((NFS_READ_SIZE / 2) * 10)))
putchar ('#');
- }
- rlen = ntohl(rpc_pkt.u.reply.data[18]);
- if ( store_block ((uchar *)pkt+sizeof(rpc_pkt.u.reply), nfs_offset, rlen) )
- return -9999;
+ rlen = ntohl(net_read_uint32(data + 18));
+
+ ret = write(net_store_fd, (char *)(data + 19), rlen);
+ if (ret < 0) {
+ perror("write");
+ return ret;
+ }
return rlen;
}
@@ -545,170 +560,116 @@ nfs_read_reply (uchar *pkt, unsigned len)
Interfaces of barebox
**************************************************************************/
-static void
-NfsTimeout (void)
+static void nfs_handler(char *packet, unsigned len)
{
- puts ("Timeout\n");
- NetState = NETLOOP_FAIL;
- return;
-}
-
-static void
-NfsHandler (uchar *pkt, unsigned dest, unsigned src, unsigned len)
-{
- int rlen;
-
-#ifdef NFS_DEBUG
- printf ("%s\n", __FUNCTION__);
-#endif
+ char *pkt = net_eth_to_udp_payload(packet);
+ int ret;
- if (dest != NfsOurPort) return;
+ debug("%s\n", __func__);
- switch (NfsState) {
+ switch (nfs_state) {
case STATE_PRCLOOKUP_PROG_MOUNT_REQ:
- rpc_lookup_reply (PROG_MOUNT, pkt, len);
- NfsState = STATE_PRCLOOKUP_PROG_NFS_REQ;
- NfsSend ();
+ ret = rpc_lookup_reply(PROG_MOUNT, pkt, len);
+ if (ret)
+ goto err_out;
+ nfs_state = STATE_PRCLOOKUP_PROG_NFS_REQ;
break;
case STATE_PRCLOOKUP_PROG_NFS_REQ:
- rpc_lookup_reply (PROG_NFS, pkt, len);
- NfsState = STATE_MOUNT_REQ;
- NfsSend ();
+ ret = rpc_lookup_reply(PROG_NFS, pkt, len);
+ if (ret)
+ goto err_out;
+ nfs_state = STATE_MOUNT_REQ;
break;
case STATE_MOUNT_REQ:
- if (nfs_mount_reply(pkt, len)) {
- puts ("*** ERROR: Cannot mount\n");
- /* just to be sure... */
- NfsState = STATE_UMOUNT_REQ;
- NfsSend ();
- } else {
- NfsState = STATE_LOOKUP_REQ;
- NfsSend ();
- }
+ ret = nfs_mount_reply(pkt, len);
+ if (ret)
+ goto err_out;
+
+ nfs_state = STATE_LOOKUP_REQ;
break;
case STATE_UMOUNT_REQ:
- if (nfs_umountall_reply(pkt, len)) {
- puts ("*** ERROR: Cannot umount\n");
- NetState = NETLOOP_FAIL;
- } else {
- puts ("\ndone\n");
- NetState = NfsDownloadState;
- }
- break;
+ ret = nfs_umountall_reply(pkt, len);
+ if (ret)
+ nfs_err = ret;
+ nfs_state = STATE_DONE;
+ return;
case STATE_LOOKUP_REQ:
- if (nfs_lookup_reply(pkt, len)) {
- puts ("*** ERROR: File lookup fail\n");
- NfsState = STATE_UMOUNT_REQ;
- NfsSend ();
- } else {
- NfsState = STATE_READ_REQ;
- nfs_offset = 0;
- nfs_len = NFS_READ_SIZE;
- NfsSend ();
- }
+ ret = nfs_lookup_reply(pkt, len);
+ if (ret)
+ goto err_umount;
+
+ nfs_state = STATE_READ_REQ;
+ nfs_offset = 0;
break;
case STATE_READLINK_REQ:
- if (nfs_readlink_reply(pkt, len)) {
- puts ("*** ERROR: Symlink fail\n");
- NfsState = STATE_UMOUNT_REQ;
- NfsSend ();
- } else {
-#ifdef NFS_DEBUG
- printf ("Symlink --> %s\n", nfs_path);
-#endif
- nfs_filename = basename (nfs_path);
- nfs_path = dirname (nfs_path);
-
- NfsState = STATE_MOUNT_REQ;
- NfsSend ();
- }
+ ret = nfs_readlink_reply(pkt, len);
+ if (ret)
+ goto err_umount;
+
+ debug("Symlink --> %s\n", nfs_path);
+
+ nfs_filename = basename(nfs_path);
+ nfs_path = dirname(nfs_path);
+
+ nfs_state = STATE_MOUNT_REQ;
break;
case STATE_READ_REQ:
- rlen = nfs_read_reply (pkt, len);
- NetSetTimeout (NFS_TIMEOUT * SECOND, NfsTimeout);
- if (rlen > 0) {
- nfs_offset += rlen;
- NfsSend ();
- }
- else if ((rlen == -NFSERR_ISDIR)||(rlen == -NFSERR_INVAL)) {
+ ret = nfs_read_reply(pkt, len);
+ nfs_timer_start = get_time_ns();
+ if (ret > 0)
+ nfs_offset += ret;
+ else if (ret == -EISDIR || ret == -EINVAL)
/* symbolic link */
- NfsState = STATE_READLINK_REQ;
- NfsSend ();
- } else {
- if ( ! rlen ) NfsDownloadState = NETLOOP_SUCCESS;
- NfsState = STATE_UMOUNT_REQ;
- NfsSend ();
- }
+ nfs_state = STATE_READLINK_REQ;
+ else
+ goto err_umount;
+
break;
}
-}
+ nfs_send();
+
+ return;
+
+err_umount:
+ nfs_state = STATE_UMOUNT_REQ;
+ nfs_err = ret;
+ nfs_send();
+ return;
+
+err_out:
+ nfs_state = STATE_DONE;
+ nfs_err = ret;
+}
-void
-NfsStart (char *p)
+static void nfs_start(char *p)
{
-#ifdef NFS_DEBUG
- printf ("%s\n", __FUNCTION__);
-#endif
- NfsDownloadState = NETLOOP_FAIL;
+ debug("%s\n", __func__);
- NfsServerIP = NetServerIP;
nfs_path = (char *)nfs_path_buff;
- if (nfs_path == NULL) {
- NetState = NETLOOP_FAIL;
- puts ("*** ERROR: Fail allocate memory\n");
- return;
- }
-
- strcpy (nfs_path, p);
+ strcpy(nfs_path, p);
nfs_filename = basename (nfs_path);
nfs_path = dirname (nfs_path);
-#if defined(CONFIG_NET_MULTI)
- printf ("Using %s device\n", eth_get_name());
-#endif
+ printf("\nFilename '%s/%s'.\nLoading: ", nfs_path, nfs_filename);
- puts ("File transfer via NFS from server "); print_IPaddr (NfsServerIP);
- puts ("; our IP address is "); print_IPaddr (NetOurIP);
+ nfs_timer_start = get_time_ns();
- /* Check if we need to send across this subnet */
- if (NetOurGatewayIP && NetOurSubnetMask) {
- IPaddr_t OurNet = NetOurIP & NetOurSubnetMask;
- IPaddr_t ServerNet = NetServerIP & NetOurSubnetMask;
+ nfs_state = STATE_PRCLOOKUP_PROG_MOUNT_REQ;
- if (OurNet != ServerNet) {
- puts ("; sending through gateway ");
- print_IPaddr (NetOurGatewayIP) ;
- }
- }
- printf ("\nFilename '%s/%s'.", nfs_path, nfs_filename);
-
- NetSetTimeout (NFS_TIMEOUT * SECOND, NfsTimeout);
- NetSetHandler (NfsHandler);
-
- NfsTimeoutCount = 0;
- NfsState = STATE_PRCLOOKUP_PROG_MOUNT_REQ;
-
- /*FIX ME !!!*/
- NfsOurPort = 1000;
-
- /* zero out server ether in case the server ip has changed */
- memset (NetServerEther, 0, 6);
-
- NfsSend ();
+ nfs_send();
}
static int do_nfs(struct command *cmdtp, int argc, char *argv[])
{
- int rcode = 0;
char *localfile;
char *remotefile;
@@ -728,23 +689,38 @@ static int do_nfs(struct command *cmdtp, int argc, char *argv[])
return 1;
}
- if (NetLoopInit(NFS) < 0)
- goto out;
+ nfs_con = net_udp_new(net_get_serverip(), 0, nfs_handler);
+ if (IS_ERR(nfs_con)) {
+ nfs_err = PTR_ERR(nfs_con);
+ goto err_udp;
+ }
+ net_udp_bind(nfs_con, 1000);
- NfsStart(remotefile);
+ nfs_err = 0;
- rcode = NetLoop();
- if (rcode < 0) {
- rcode = 1;
- goto out;
- }
+ nfs_start(remotefile);
- /* NetLoop ok, update environment */
- netboot_update_env();
+ while (nfs_state != STATE_DONE) {
+ if (ctrlc()) {
+ nfs_err = -EINTR;
+ break;
+ }
+ net_poll();
+ if (is_timeout(nfs_timer_start, NFS_TIMEOUT * SECOND))
+ break;
+ }
-out:
+ net_unregister(nfs_con);
+err_udp:
close(net_store_fd);
- return rcode;
+ if (nfs_err) {
+ printf("NFS failed: %s\n", strerror(-nfs_err));
+ unlink(localfile);
+ }
+
+ printf("\n");
+
+ return nfs_err == 0 ? 0 : 1;
}
static const __maybe_unused char cmd_nfs_help[] =
diff --git a/net/ping.c b/net/ping.c
index 1bc481af44..440e229ba0 100644
--- a/net/ping.c
+++ b/net/ping.c
@@ -2,103 +2,109 @@
#include <command.h>
#include <clock.h>
#include <net.h>
+#include <errno.h>
+#include <linux/err.h>
-static ushort PingSeqNo;
+static uint16_t ping_sequence_number;
-static IPaddr_t NetPingIP; /* the ip address to ping */
+static IPaddr_t net_ping_ip; /* the ip address to ping */
-static int PingSend(void)
-{
- static uchar mac[6];
- IP_t *ip;
- ushort *s;
- uchar *pkt;
-
- /* XXX always send arp request */
-
- memcpy(mac, NetEtherNullAddr, 6);
-
- pr_debug("sending ARP for %08lx\n", NetPingIP);
-
- NetArpWaitPacketIP = NetPingIP;
- NetArpWaitPacketMAC = mac;
-
- pkt = NetArpWaitTxPacket;
- pkt += NetSetEther(pkt, mac, PROT_IP);
-
- ip = (IP_t *)pkt;
-
- /*
- * Construct an IP and ICMP header. (need to set no fragment bit - XXX)
- */
- ip->ip_hl_v = 0x45; /* IP_HDR_SIZE / 4 (not including UDP) */
- ip->ip_tos = 0;
- ip->ip_len = htons(IP_HDR_SIZE_NO_UDP + 8);
- ip->ip_id = htons(NetIPID++);
- ip->ip_off = htons(0x4000); /* No fragmentation */
- ip->ip_ttl = 255;
- ip->ip_p = 0x01; /* ICMP */
- ip->ip_sum = 0;
- NetCopyIP((void*)&ip->ip_src, &NetOurIP); /* already in network byte order */
- NetCopyIP((void*)&ip->ip_dst, &NetPingIP); /* - "" - */
- ip->ip_sum = ~NetCksum((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2);
-
- s = &ip->udp_src; /* XXX ICMP starts here */
- s[0] = htons(0x0800); /* echo-request, code */
- s[1] = 0; /* checksum */
- s[2] = 0; /* identifier */
- s[3] = htons(PingSeqNo++); /* sequence number */
- s[1] = ~NetCksum((uchar *)s, 8/2);
-
- /* size of the waiting packet */
- NetArpWaitTxPacketSize = (pkt - NetArpWaitTxPacket) + IP_HDR_SIZE_NO_UDP + 8;
-
- /* and do the ARP request */
- NetArpWaitTimerStart = get_time_ns();
- ArpRequest();
- return 1; /* waiting */
-}
+#define PING_STATE_INIT 0
+#define PING_STATE_SUCCESS 1
+
+static int ping_state;
-static void
-PingTimeout (void)
+static struct net_connection *ping_con;
+
+static int ping_send(void)
{
- eth_halt();
- NetState = NETLOOP_FAIL; /* we did not get the reply */
+ unsigned char *payload;
+ struct icmphdr *icmp;
+ uint64_t ts;
+
+ icmp = ping_con->icmp;
+
+ icmp->type = ICMP_ECHO_REQUEST;
+ icmp->code = 0;
+ icmp->checksum = 0;
+ icmp->un.echo.id = 0;
+ icmp->un.echo.sequence = htons(ping_sequence_number);
+
+ ping_sequence_number++;
+
+ payload = (char *)(icmp + 1);
+ ts = get_time_ns();
+ memcpy(payload, &ts, sizeof(ts));
+ payload[8] = 0xab;
+ payload[9] = 0xcd;
+ return net_icmp_send(ping_con, 9);
}
-static void
-PingHandler (uchar * pkt, unsigned dest, unsigned src, unsigned len)
+void ping_handler(char *pkt, unsigned len)
{
IPaddr_t tmp;
- IP_t *ip = (IP_t *)pkt;
+ struct iphdr *ip = net_eth_to_iphdr(pkt);
- tmp = NetReadIP((void *)&ip->ip_src);
- if (tmp != NetPingIP)
+ tmp = net_read_ip((void *)&ip->saddr);
+ if (tmp != net_ping_ip)
return;
- NetState = NETLOOP_SUCCESS;
+ ping_state = PING_STATE_SUCCESS;
}
int do_ping(struct command *cmdtp, int argc, char *argv[])
{
- if (argc < 2 || string_to_ip(argv[1], &NetPingIP))
+ int ret;
+ uint64_t ping_start = 0;
+
+ if (argc < 2)
return COMMAND_ERROR_USAGE;
- if (NetLoopInit(PING) < 0)
+ net_ping_ip = resolv(argv[1]);
+ if (!net_ping_ip) {
+ printf("unknown host %s\n", argv[1]);
return 1;
+ }
- NetSetTimeout (10 * SECOND, PingTimeout);
- NetSetHandler (PingHandler);
- PingSend();
+ ping_con = net_icmp_new(net_ping_ip, ping_handler);
+ if (IS_ERR(ping_con)) {
+ ret = PTR_ERR(ping_con);
+ goto out;
+ }
- if (NetLoop() < 0) {
- printf("ping failed; host %s is not alive\n", argv[1]);
- return 1;
+ ping_start = get_time_ns();
+ ret = ping_send();
+ if (ret)
+ goto out_unreg;
+
+ ping_state = PING_STATE_INIT;
+ ping_sequence_number = 0;
+
+ while (ping_state == PING_STATE_INIT) {
+ if (ctrlc()) {
+ ret = -EINTR;
+ break;
+ }
+
+ net_poll();
+
+ if (is_timeout(ping_start, 10 * SECOND)) {
+ ping_start = get_time_ns();
+ ret = ping_send();
+ if (ret)
+ goto out_unreg;
+ }
}
- printf("host %s is alive\n", argv[1]);
+ if (!ret)
+ printf("host %s is alive\n", argv[1]);
- return 0;
+out_unreg:
+ net_unregister(ping_con);
+out:
+ if (ret)
+ printf("ping failed: %s\n", strerror(-ret));
+ return ping_state == PING_STATE_SUCCESS ? 0 : 1;
}
BAREBOX_CMD_START(ping)
diff --git a/net/rarp.c b/net/rarp.c
deleted file mode 100644
index 24818f8dba..0000000000
--- a/net/rarp.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * (C) Copyright 2000-2002
- * 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>
-#include <command.h>
-#include <clock.h>
-#include <net.h>
-#include "nfs.h"
-#include "rarp.h"
-#include "tftp.h"
-
-#define TIMEOUT 5 /* Seconds before trying BOOTP again */
-#ifndef CONFIG_NET_RETRY_COUNT
-# define TIMEOUT_COUNT 5 /* # of timeouts before giving up */
-#else
-# define TIMEOUT_COUNT (CONFIG_NET_RETRY_COUNT)
-#endif
-
-
-int RarpTry;
-
-/*
- * Handle a RARP received packet.
- */
-static void
-RarpHandler(uchar * dummi0, unsigned dummi1, unsigned dummi2, unsigned dummi3)
-{
-#ifdef DEBUG
- puts ("Got good RARP\n");
-#endif
- NetState = NETLOOP_SUCCESS;
-}
-
-
-/*
- * Timeout on BOOTP request.
- */
-static void
-RarpTimeout(void)
-{
- NetSetTimeout (TIMEOUT * SECOND, RarpTimeout);
- RarpRequest ();
-}
-
-
-void
-RarpRequest (void)
-{
- int i;
- uchar *pkt;
- ARP_t * rarp;
-
- NetOurIP = 0;
- RarpTry = 0;
-
- printf("RARP broadcast %d\n", ++RarpTry);
- pkt = NetTxPacket;
-
- pkt += NetSetEther(pkt, NetBcastAddr, PROT_RARP);
-
- rarp = (ARP_t *)pkt;
-
- rarp->ar_hrd = htons (ARP_ETHER);
- rarp->ar_pro = htons (PROT_IP);
- rarp->ar_hln = 6;
- rarp->ar_pln = 4;
- rarp->ar_op = htons (RARPOP_REQUEST);
- memcpy (&rarp->ar_data[0], NetOurEther, 6); /* source ET addr */
- memcpy (&rarp->ar_data[6], &NetOurIP, 4); /* source IP addr */
- memcpy (&rarp->ar_data[10], NetOurEther, 6); /* dest ET addr = source ET addr ??*/
- /* dest. IP addr set to broadcast */
- for (i = 0; i <= 3; i++) {
- rarp->ar_data[16 + i] = 0xff;
- }
-
- NetSendPacket(NetTxPacket, (pkt - NetTxPacket) + ARP_HDR_SIZE);
-
- NetSetTimeout(TIMEOUT * SECOND, RarpTimeout);
- NetSetHandler(RarpHandler);
-}
-
diff --git a/net/sntp.h b/net/sntp.h
deleted file mode 100644
index 8a097bfa38..0000000000
--- a/net/sntp.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * (C) Masami Komiya <mkomiya@sonare.it> 2005
- *
- * 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 __SNTP_H__
-#define __SNTP_H__
-
-#define NTP_SERVICE_PORT 123
-#define SNTP_PACKET_LEN 48
-
-
-/* Leap Indicator */
-#define NTP_LI_NOLEAP 0x0
-#define NTP_LI_61SECS 0x1
-#define NTP_LI_59SECS 0x2
-#define NTP_LI_ALARM 0x3
-
-/* Version */
-
-#define NTP_VERSION 4
-
-/* Mode */
-#define NTP_MODE_RESERVED 0
-#define NTP_MODE_SYMACTIVE 1 /* Symmetric Active */
-#define NTP_MODE_SYMPASSIVE 2 /* Symmetric Passive */
-#define NTP_MODE_CLIENT 3
-#define NTP_MODE_SERVER 4
-#define NTP_MODE_BROADCAST 5
-#define NTP_MODE_NTPCTRL 6 /* Reserved for NTP control message */
-#define NTP_MODE_PRIVATE 7 /* Reserved for private use */
-
-struct sntp_pkt_t {
-#if __LITTLE_ENDIAN
- uchar mode:3;
- uchar vn:3;
- uchar li:2;
-#else
- uchar li:2;
- uchar vn:3;
- uchar mode:3;
-#endif
- uchar stratum;
- uchar poll;
- uchar precision;
- uint root_delay;
- uint root_dispersion;
- uint reference_id;
- unsigned long long reference_timestamp;
- unsigned long long originate_timestamp;
- unsigned long long receive_timestamp;
- unsigned long long transmit_timestamp;
-};
-
-extern void SntpStart (void); /* Begin SNTP */
-
-#endif /* __SNTP_H__ */
diff --git a/net/tftp.c b/net/tftp.c
index e8a8a3a899..38d16bcbd2 100644
--- a/net/tftp.c
+++ b/net/tftp.c
@@ -13,9 +13,9 @@
#include <errno.h>
#include <libgen.h>
#include <fcntl.h>
-#include "tftp.h"
+#include <linux/err.h>
-#define WELL_KNOWN_PORT 69 /* Well known TFTP port # */
+#define TFTP_PORT 69 /* Well known TFTP port # */
#define TIMEOUT 5 /* Seconds to timeout for a lost pkt */
# define TIMEOUT_COUNT 10 /* # of timeouts before giving up */
/* (for checking the image size) */
@@ -32,60 +32,45 @@
#define TFTP_OACK 6
-static int TftpServerPort; /* The UDP port at their end */
-static int TftpOurPort; /* The UDP port at our end */
-static ulong TftpBlock; /* packet sequence number */
-static ulong TftpLastBlock; /* last packet sequence number received */
-static ulong TftpBlockWrap; /* count of sequence number wraparounds */
-static ulong TftpBlockWrapOffset; /* memory offset due to wrapping */
-static int TftpState;
+static int tftp_server_port; /* The UDP port at their end */
+static unsigned int tftp_block; /* packet sequence number */
+static unsigned int tftp_last_block; /* last packet sequence number received */
+static unsigned int tftp_block_wrap; /* count of sequence number wraparounds */
+static unsigned int tftp_block_wrap_offset; /* memory offset due to wrapping */
+static int tftp_state;
+static uint64_t tftp_timer_start;
+static int tftp_err;
#define STATE_RRQ 1
#define STATE_DATA 2
#define STATE_OACK 3
+#define STATE_DONE 4
#define TFTP_BLOCK_SIZE 512 /* default TFTP block size */
-#define TFTP_SEQUENCE_SIZE ((ulong)(1<<16)) /* sequence number is 16 bit */
+#define TFTP_SEQUENCE_SIZE ((unsigned long)(1<<16)) /* sequence number is 16 bit */
static char *tftp_filename;
-
+static struct net_connection *tftp_con;
static int net_store_fd;
-static int store_block(unsigned block, uchar * src, unsigned len)
+static int tftp_send(void)
{
- ulong offset = block * TFTP_BLOCK_SIZE + TftpBlockWrapOffset;
- ulong newsize = offset + len;
- int ret;
-
- ret = write(net_store_fd, src, len);
- if (ret < 0)
- return ret;
-
- if (NetBootFileXferSize < newsize)
- NetBootFileXferSize = newsize;
- return 0;
-}
-
-static void TftpSend(void)
-{
- uchar *pkt;
- uchar *xp;
+ unsigned char *pkt;
+ unsigned char *xp;
int len = 0;
- ushort *s;
+ uint16_t *s;
+ unsigned char *packet = net_udp_get_payload(tftp_con);
+ int ret;
- /*
- * We will always be sending some sort of packet, so
- * cobble together the packet headers now.
- */
- pkt = NetTxPacket + NetEthHdrSize() + IP_HDR_SIZE;
+ pkt = packet;
- switch (TftpState) {
+ switch (tftp_state) {
case STATE_RRQ:
xp = pkt;
- s = (ushort *)pkt;
+ s = (uint16_t *)pkt;
*s++ = htons(TFTP_RRQ);
- pkt = (uchar *)s;
- pkt += sprintf((uchar *)pkt, "%s%coctet%ctimeout%c%d",
+ pkt = (unsigned char *)s;
+ pkt += sprintf((unsigned char *)pkt, "%s%coctet%ctimeout%c%d",
tftp_filename, 0, 0, 0, TIMEOUT) + 1;
len = pkt - xp;
break;
@@ -93,44 +78,36 @@ static void TftpSend(void)
case STATE_DATA:
case STATE_OACK:
xp = pkt;
- s = (ushort *)pkt;
+ s = (uint16_t *)pkt;
*s++ = htons(TFTP_ACK);
- *s++ = htons(TftpBlock);
- pkt = (uchar *)s;
+ *s++ = htons(tftp_block);
+ pkt = (unsigned char *)s;
len = pkt - xp;
break;
}
- NetSendUDPPacket(NetServerEther, NetServerIP, TftpServerPort,
- TftpOurPort, len);
-}
+ ret = net_udp_send(tftp_con, len);
-static void TftpTimeout(void)
-{
- puts("T ");
- NetSetTimeout(TIMEOUT * SECOND, TftpTimeout);
- TftpSend();
+ return ret;
}
-static void TftpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len)
+static void tftp_handler(char *packet, unsigned len)
{
- ushort proto;
- ushort *s;
-
- if (dest != TftpOurPort)
- return;
-
- if (TftpState != STATE_RRQ && src != TftpServerPort)
- return;
+ uint16_t proto;
+ uint16_t *s;
+ char *pkt = net_eth_to_udp_payload(packet);
+ struct udphdr *udp = net_eth_to_udphdr(packet);
+ int ret;
+ len = net_eth_to_udplen(packet);
if (len < 2)
return;
len -= 2;
/* warning: don't use increment (++) in ntohs() macros!! */
- s = (ushort *)pkt;
+ s = (uint16_t *)pkt;
proto = *s++;
- pkt = (uchar *)s;
+ pkt = (unsigned char *)s;
switch (ntohs(proto)) {
case TFTP_RRQ:
case TFTP_WRQ:
@@ -140,16 +117,17 @@ static void TftpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len)
break;
case TFTP_OACK:
- debug("Got OACK: %s %s\n", pkt, pkt+strlen(pkt)+1);
- TftpState = STATE_OACK;
- TftpServerPort = src;
- TftpSend(); /* Send ACK */
+ debug("Got OACK: %s %s\n", pkt, pkt + strlen(pkt) + 1);
+ tftp_state = STATE_OACK;
+ tftp_server_port = ntohs(udp->uh_sport);
+ tftp_con->udp->uh_dport = udp->uh_sport;
+ tftp_send(); /* Send ACK */
break;
case TFTP_DATA:
if (len < 2)
return;
len -= 2;
- TftpBlock = ntohs(*(ushort *)pkt);
+ tftp_block = ntohs(*(uint16_t *)pkt);
/*
* RFC1350 specifies that the first data packet will
@@ -157,49 +135,50 @@ static void TftpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len)
* number of 0 this means that there was a wrap
* around of the (16 bit) counter.
*/
- if (TftpBlock == 0) {
- TftpBlockWrap++;
- TftpBlockWrapOffset += TFTP_BLOCK_SIZE * TFTP_SEQUENCE_SIZE;
- printf ("\n\t %lu MB received\n\t ", TftpBlockWrapOffset>>20);
+ if (tftp_block == 0) {
+ tftp_block_wrap++;
+ tftp_block_wrap_offset += TFTP_BLOCK_SIZE * TFTP_SEQUENCE_SIZE;
} else {
- if (((TftpBlock - 1) % 10) == 0) {
+ if (((tftp_block - 1) % 10) == 0) {
putchar('#');
- } else if ((TftpBlock % (10 * HASHES_PER_LINE)) == 0) {
+ } else if ((tftp_block % (10 * HASHES_PER_LINE)) == 0) {
puts("\n\t ");
}
}
- if (TftpState == STATE_RRQ)
+ if (tftp_state == STATE_RRQ)
debug("Server did not acknowledge timeout option!\n");
- if (TftpState == STATE_RRQ || TftpState == STATE_OACK) {
+ if (tftp_state == STATE_RRQ || tftp_state == STATE_OACK) {
/* first block received */
- TftpState = STATE_DATA;
- TftpServerPort = src;
- TftpLastBlock = 0;
- TftpBlockWrap = 0;
- TftpBlockWrapOffset = 0;
-
- if (TftpBlock != 1) { /* Assertion */
- printf("\nTFTP error: "
- "First block is not block 1 (%ld)\n"
- "Starting again\n\n",
- TftpBlock);
- NetState = NETLOOP_FAIL;
+ tftp_state = STATE_DATA;
+ tftp_con->udp->uh_dport = udp->uh_sport;
+ tftp_server_port = ntohs(udp->uh_sport);
+ tftp_last_block = 0;
+ tftp_block_wrap = 0;
+ tftp_block_wrap_offset = 0;
+
+ if (tftp_block != 1) { /* Assertion */
+ printf("error: First block is not block 1 (%ld)\n",
+ tftp_block);
+ tftp_err = -EINVAL;
+ tftp_state = STATE_DONE;
break;
}
}
- if (TftpBlock == TftpLastBlock)
+ if (tftp_block == tftp_last_block)
/* Same block again; ignore it. */
break;
- TftpLastBlock = TftpBlock;
- NetSetTimeout(TIMEOUT * SECOND, TftpTimeout);
+ tftp_last_block = tftp_block;
+ tftp_timer_start = get_time_ns();
- if (store_block(TftpBlock - 1, pkt + 2, len) < 0) {
+ ret = write(net_store_fd, pkt + 2, len);
+ if (ret < 0) {
perror("write");
- NetState = NETLOOP_FAIL;
+ tftp_err = -errno;
+ tftp_state = STATE_DONE;
return;
}
@@ -207,58 +186,31 @@ static void TftpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len)
* Acknowledge the block just received, which will prompt
* the server for the next one.
*/
- TftpSend();
-
- if (len < TFTP_BLOCK_SIZE) {
- /*
- * We received the whole thing. Try to
- * run it.
- */
- puts("\ndone\n");
- NetState = NETLOOP_SUCCESS;
- }
+ tftp_send();
+
+ if (len < TFTP_BLOCK_SIZE)
+ tftp_state = STATE_DONE;
+
break;
case TFTP_ERROR:
- printf("\nTFTP error: '%s' (%d)\n",
- pkt + 2, ntohs(*(ushort *)pkt));
- NetState = NETLOOP_FAIL;
+ debug("\nTFTP error: '%s' (%d)\n",
+ pkt + 2, ntohs(*(uint16_t *)pkt));
+ switch (ntohs(*(uint16_t *)pkt)) {
+ case 1: tftp_err = -ENOENT; break;
+ case 2: tftp_err = -EACCES; break;
+ default: tftp_err = -EINVAL; break;
+ }
+ tftp_state = STATE_DONE;
break;
}
}
-void TftpStart(char *filename)
-{
- char ip1[16], ip2[16];
-
- tftp_filename = filename;
-
- printf("TFTP from server %s; our IP address is %s\n"
- "\nFilename '%s'.\nLoading: *\b",
- ip_to_string(NetServerIP, ip1),
- ip_to_string(NetOurIP, ip2),
- tftp_filename);
-
- NetSetTimeout(TIMEOUT * SECOND, TftpTimeout);
- NetSetHandler(TftpHandler);
-
- TftpServerPort = WELL_KNOWN_PORT;
- TftpState = STATE_RRQ;
- /* Use a pseudo-random port */
- TftpOurPort = 1024 + ((unsigned int)get_time_ns() % 3072);
- TftpBlock = 0;
-
- /* zero out server ether in case the server ip has changed */
- memset(NetServerEther, 0, 6);
-
- TftpSend();
-}
-
static int do_tftpb(struct command *cmdtp, int argc, char *argv[])
{
- int rcode = 0;
- char *localfile;
- char *remotefile;
+ char *localfile;
+ char *remotefile;
+ char ip1[16];
if (argc < 2)
return COMMAND_ERROR_USAGE;
@@ -276,22 +228,51 @@ static int do_tftpb(struct command *cmdtp, int argc, char *argv[])
return 1;
}
- if (NetLoopInit(TFTP) < 0)
- goto out;
+ tftp_con = net_udp_new(net_get_serverip(), TFTP_PORT, tftp_handler);
+ if (IS_ERR(tftp_con)) {
+ tftp_err = PTR_ERR(tftp_con);
+ goto out_close;
+ }
- TftpStart(remotefile);
+ tftp_filename = remotefile;
- if (NetLoop() < 0) {
- rcode = 1;
- goto out;
- }
+ printf("TFTP from server %s; Filename: '%s'\nLoading: ",
+ ip_to_string(net_get_serverip(), ip1),
+ tftp_filename);
+
+ tftp_timer_start = get_time_ns();
+ tftp_state = STATE_RRQ;
+ tftp_block = 0;
- /* NetLoop ok, update environment */
- netboot_update_env();
+ tftp_err = tftp_send();
+ if (tftp_err)
+ goto out_unreg;
-out:
+ while (tftp_state != STATE_DONE) {
+ if (ctrlc()) {
+ tftp_err = -EINTR;
+ break;
+ }
+ net_poll();
+ if (is_timeout(tftp_timer_start, SECOND)) {
+ tftp_timer_start = get_time_ns();
+ printf("T ");
+ tftp_send();
+ }
+ }
+out_unreg:
+ net_unregister(tftp_con);
+out_close:
close(net_store_fd);
- return rcode;
+
+ if (tftp_err) {
+ printf("\ntftp failed: %s\n", strerror(-tftp_err));
+ unlink(localfile);
+ }
+
+ printf("\n");
+
+ return tftp_err == 0 ? 0 : 1;
}
static const __maybe_unused char cmd_tftp_help[] =