mirror of
https://github.com/u-boot/u-boot.git
synced 2025-04-15 17:34:43 +00:00
net: lwip: add DHCP support and dhcp commmand
Add what it takes to enable NETDEVICES with NET_LWIP and enable DHCP as well as the dhcp command. CMD_TFTPBOOT is selected by BOOTMETH_EFI due to this code having an implicit dependency on do_tftpb(). Note that PXE is likely non-fonctional with NET_LWIP (or at least not 100% functional) because DHCP option 209 is not supported by the lwIP library. Therefore, BOOTP_PXE_DHCP_OPTION cannot be enabled. Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org> Tested-by: Ilias Apalodimas <ilias.apalodimas@linaro.org> Acked-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
This commit is contained in:
parent
1c41a7afaa
commit
98ad145db6
21 changed files with 573 additions and 62 deletions
|
@ -33,7 +33,7 @@ static void setup_fec(void)
|
||||||
setbits_le32(&gpr->gpr[1], BIT(22));
|
setbits_le32(&gpr->gpr[1], BIT(22));
|
||||||
}
|
}
|
||||||
|
|
||||||
#if CONFIG_IS_ENABLED(NET)
|
#if CONFIG_IS_ENABLED(NET) || CONFIG_IS_ENABLED(NET_LWIP)
|
||||||
int board_phy_config(struct phy_device *phydev)
|
int board_phy_config(struct phy_device *phydev)
|
||||||
{
|
{
|
||||||
if (phydev->drv->config)
|
if (phydev->drv->config)
|
||||||
|
|
|
@ -29,7 +29,7 @@ static void setup_fec(void)
|
||||||
setbits_le32(&gpr->gpr[1], BIT(22));
|
setbits_le32(&gpr->gpr[1], BIT(22));
|
||||||
}
|
}
|
||||||
|
|
||||||
#if CONFIG_IS_ENABLED(NET)
|
#if CONFIG_IS_ENABLED(NET) || CONFIG_IS_ENABLED(NET_LWIP)
|
||||||
int board_phy_config(struct phy_device *phydev)
|
int board_phy_config(struct phy_device *phydev)
|
||||||
{
|
{
|
||||||
if (phydev->drv->config)
|
if (phydev->drv->config)
|
||||||
|
|
|
@ -900,7 +900,8 @@ int board_late_init(void)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* CPSW plat */
|
/* CPSW plat */
|
||||||
#if CONFIG_IS_ENABLED(NET) && !CONFIG_IS_ENABLED(OF_CONTROL)
|
#if (CONFIG_IS_ENABLED(NET) || CONFIG_IS_ENABLED(NET_LWIP)) && \
|
||||||
|
!CONFIG_IS_ENABLED(OF_CONTROL)
|
||||||
struct cpsw_slave_data slave_data[] = {
|
struct cpsw_slave_data slave_data[] = {
|
||||||
{
|
{
|
||||||
.slave_reg_ofs = CPSW_SLAVE0_OFFSET,
|
.slave_reg_ofs = CPSW_SLAVE0_OFFSET,
|
||||||
|
|
|
@ -491,7 +491,8 @@ int board_late_init_xilinx(void)
|
||||||
ret |= env_set_by_index("uuid", id, uuid);
|
ret |= env_set_by_index("uuid", id, uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!CONFIG_IS_ENABLED(NET))
|
if (!(CONFIG_IS_ENABLED(NET) ||
|
||||||
|
CONFIG_IS_ENABLED(NET_LWIP)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (i = 0; i < EEPROM_HDR_NO_OF_MAC_ADDR; i++) {
|
for (i = 0; i < EEPROM_HDR_NO_OF_MAC_ADDR; i++) {
|
||||||
|
|
100
cmd/Kconfig
100
cmd/Kconfig
|
@ -1789,12 +1789,16 @@ config CMD_AB_SELECT
|
||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
|
||||||
if NET
|
if NET || NET_LWIP
|
||||||
|
|
||||||
menuconfig CMD_NET
|
menuconfig CMD_NET
|
||||||
bool "Network commands"
|
bool "Network commands"
|
||||||
default y
|
default y
|
||||||
|
|
||||||
|
endif
|
||||||
|
|
||||||
|
if NET
|
||||||
|
|
||||||
if CMD_NET
|
if CMD_NET
|
||||||
|
|
||||||
config CMD_BOOTP
|
config CMD_BOOTP
|
||||||
|
@ -1803,12 +1807,6 @@ config CMD_BOOTP
|
||||||
help
|
help
|
||||||
bootp - boot image via network using BOOTP/TFTP protocol
|
bootp - boot image via network using BOOTP/TFTP protocol
|
||||||
|
|
||||||
config CMD_DHCP
|
|
||||||
bool "dhcp"
|
|
||||||
depends on CMD_BOOTP
|
|
||||||
help
|
|
||||||
Boot image via network using DHCP/TFTP protocol
|
|
||||||
|
|
||||||
config CMD_DHCP6
|
config CMD_DHCP6
|
||||||
bool "dhcp6"
|
bool "dhcp6"
|
||||||
depends on IPV6
|
depends on IPV6
|
||||||
|
@ -1952,12 +1950,6 @@ config BOOTP_VCI_STRING
|
||||||
default "U-Boot.arm" if ARM
|
default "U-Boot.arm" if ARM
|
||||||
default "U-Boot"
|
default "U-Boot"
|
||||||
|
|
||||||
config CMD_TFTPBOOT
|
|
||||||
bool "tftpboot"
|
|
||||||
default y
|
|
||||||
help
|
|
||||||
tftpboot - load file via network using TFTP protocol
|
|
||||||
|
|
||||||
config CMD_TFTPPUT
|
config CMD_TFTPPUT
|
||||||
bool "tftp put"
|
bool "tftp put"
|
||||||
depends on CMD_TFTPBOOT
|
depends on CMD_TFTPBOOT
|
||||||
|
@ -2017,29 +2009,6 @@ config CMD_WGET
|
||||||
wget is a simple command to download kernel, or other files,
|
wget is a simple command to download kernel, or other files,
|
||||||
from a http server over TCP.
|
from a http server over TCP.
|
||||||
|
|
||||||
config CMD_MII
|
|
||||||
bool "mii"
|
|
||||||
imply CMD_MDIO
|
|
||||||
help
|
|
||||||
If set, allows 802.3(clause 22) MII Management functions interface access
|
|
||||||
The management interface specified in Clause 22 provides
|
|
||||||
a simple, two signal, serial interface to connect a
|
|
||||||
Station Management entity and a managed PHY for providing access
|
|
||||||
to management parameters and services.
|
|
||||||
The interface is referred to as the MII management interface.
|
|
||||||
|
|
||||||
config MII_INIT
|
|
||||||
bool "Call mii_init() in the mii command"
|
|
||||||
depends on CMD_MII && (MPC8XX_FEC || FSLDMAFE || MCFFEC)
|
|
||||||
|
|
||||||
config CMD_MDIO
|
|
||||||
bool "mdio"
|
|
||||||
depends on PHYLIB
|
|
||||||
help
|
|
||||||
If set, allows Enable 802.3(clause 45) MDIO interface registers access
|
|
||||||
The MDIO interface is orthogonal to the MII interface and extends
|
|
||||||
it by adding access to more registers through indirect addressing.
|
|
||||||
|
|
||||||
config CMD_PING
|
config CMD_PING
|
||||||
bool "ping"
|
bool "ping"
|
||||||
help
|
help
|
||||||
|
@ -2088,7 +2057,7 @@ config IPV6_ROUTER_DISCOVERY
|
||||||
help
|
help
|
||||||
Will automatically perform router solicitation on first IPv6
|
Will automatically perform router solicitation on first IPv6
|
||||||
network operation
|
network operation
|
||||||
endif
|
endif # if CMD_NET
|
||||||
|
|
||||||
config CMD_ETHSW
|
config CMD_ETHSW
|
||||||
bool "ethsw"
|
bool "ethsw"
|
||||||
|
@ -2098,6 +2067,56 @@ config CMD_ETHSW
|
||||||
operations such as enabling / disabling a port and
|
operations such as enabling / disabling a port and
|
||||||
viewing/maintaining the filtering database (FDB)
|
viewing/maintaining the filtering database (FDB)
|
||||||
|
|
||||||
|
config CMD_WOL
|
||||||
|
bool "wol"
|
||||||
|
help
|
||||||
|
Wait for wake-on-lan Magic Packet
|
||||||
|
|
||||||
|
endif # if NET
|
||||||
|
|
||||||
|
if NET || NET_LWIP
|
||||||
|
|
||||||
|
if CMD_NET
|
||||||
|
|
||||||
|
config CMD_DHCP
|
||||||
|
bool "dhcp"
|
||||||
|
select PROT_DHCP_LWIP if NET_LWIP
|
||||||
|
help
|
||||||
|
Boot image via network using DHCP/TFTP protocol
|
||||||
|
|
||||||
|
config CMD_MII
|
||||||
|
bool "mii"
|
||||||
|
imply CMD_MDIO
|
||||||
|
help
|
||||||
|
If set, allows 802.3(clause 22) MII Management functions interface access
|
||||||
|
The management interface specified in Clause 22 provides
|
||||||
|
a simple, two signal, serial interface to connect a
|
||||||
|
Station Management entity and a managed PHY for providing access
|
||||||
|
to management parameters and services.
|
||||||
|
The interface is referred to as the MII management interface.
|
||||||
|
|
||||||
|
config MII_INIT
|
||||||
|
bool "Call mii_init() in the mii command"
|
||||||
|
depends on CMD_MII && (MPC8XX_FEC || FSLDMAFE || MCFFEC)
|
||||||
|
|
||||||
|
config CMD_MDIO
|
||||||
|
bool "mdio"
|
||||||
|
depends on PHYLIB
|
||||||
|
help
|
||||||
|
If set, allows Enable 802.3(clause 45) MDIO interface registers access
|
||||||
|
The MDIO interface is orthogonal to the MII interface and extends
|
||||||
|
it by adding access to more registers through indirect addressing.
|
||||||
|
|
||||||
|
config CMD_TFTPBOOT
|
||||||
|
bool "tftp"
|
||||||
|
select PROT_UDP_LWIP if NET_LWIP
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
tftpboot - load file via network using TFTP protocol
|
||||||
|
Currently a placeholder (not implemented) when NET_LWIP=y.
|
||||||
|
|
||||||
|
endif # if CMD_NET
|
||||||
|
|
||||||
config CMD_PXE
|
config CMD_PXE
|
||||||
bool "pxe"
|
bool "pxe"
|
||||||
select PXE_UTILS
|
select PXE_UTILS
|
||||||
|
@ -2105,12 +2124,7 @@ config CMD_PXE
|
||||||
help
|
help
|
||||||
Boot image via network using PXE protocol
|
Boot image via network using PXE protocol
|
||||||
|
|
||||||
config CMD_WOL
|
endif # if NET || NET_LWIP
|
||||||
bool "wol"
|
|
||||||
help
|
|
||||||
Wait for wake-on-lan Magic Packet
|
|
||||||
|
|
||||||
endif
|
|
||||||
|
|
||||||
menu "Misc commands"
|
menu "Misc commands"
|
||||||
|
|
||||||
|
|
|
@ -127,7 +127,11 @@ obj-y += legacy-mtd-utils.o
|
||||||
endif
|
endif
|
||||||
obj-$(CONFIG_CMD_MUX) += mux.o
|
obj-$(CONFIG_CMD_MUX) += mux.o
|
||||||
obj-$(CONFIG_CMD_NAND) += nand.o
|
obj-$(CONFIG_CMD_NAND) += nand.o
|
||||||
obj-$(CONFIG_CMD_NET) += net.o
|
ifdef CONFIG_CMD_NET
|
||||||
|
obj-$(CONFIG_NET) += net.o
|
||||||
|
obj-$(CONFIG_NET_LWIP) += net-lwip.o
|
||||||
|
CFLAGS_net-lwip.o := -I$(srctree)/lib/lwip/lwip/src/include -I$(srctree)/lib/lwip/u-boot
|
||||||
|
endif
|
||||||
obj-$(CONFIG_ENV_SUPPORT) += nvedit.o
|
obj-$(CONFIG_ENV_SUPPORT) += nvedit.o
|
||||||
obj-$(CONFIG_CMD_NVEDIT_EFI) += nvedit_efi.o
|
obj-$(CONFIG_CMD_NVEDIT_EFI) += nvedit_efi.o
|
||||||
obj-$(CONFIG_CMD_ONENAND) += onenand.o
|
obj-$(CONFIG_CMD_ONENAND) += onenand.o
|
||||||
|
|
|
@ -133,7 +133,7 @@ int do_bootvx(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
|
||||||
else
|
else
|
||||||
addr = hextoul(argv[1], NULL);
|
addr = hextoul(argv[1], NULL);
|
||||||
|
|
||||||
#if defined(CONFIG_CMD_NET)
|
#if defined(CONFIG_CMD_NET) && !defined(CONFIG_NET_LWIP)
|
||||||
/*
|
/*
|
||||||
* Check to see if we need to tftp the image ourselves
|
* Check to see if we need to tftp the image ourselves
|
||||||
* before starting
|
* before starting
|
||||||
|
|
13
cmd/net-lwip.c
Normal file
13
cmd/net-lwip.c
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0+
|
||||||
|
/* Copyright (C) 2024 Linaro Ltd. */
|
||||||
|
|
||||||
|
#include <command.h>
|
||||||
|
#include <net.h>
|
||||||
|
|
||||||
|
#if defined(CONFIG_CMD_DHCP)
|
||||||
|
U_BOOT_CMD(
|
||||||
|
dhcp, 3, 1, do_dhcp,
|
||||||
|
"boot image via network using DHCP/TFTP protocol",
|
||||||
|
"[loadAddress] [[hostIPaddr:]bootfilename]"
|
||||||
|
);
|
||||||
|
#endif
|
|
@ -484,7 +484,7 @@ static int initr_boot_led_on(void)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_CMD_NET
|
#if defined(CONFIG_CMD_NET)
|
||||||
static int initr_net(void)
|
static int initr_net(void)
|
||||||
{
|
{
|
||||||
puts("Net: ");
|
puts("Net: ");
|
||||||
|
@ -749,7 +749,7 @@ static init_fnc_t init_sequence_r[] = {
|
||||||
#ifdef CONFIG_PCI_ENDPOINT
|
#ifdef CONFIG_PCI_ENDPOINT
|
||||||
pci_ep_init,
|
pci_ep_init,
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_CMD_NET
|
#if defined(CONFIG_CMD_NET)
|
||||||
INIT_FUNC_WATCHDOG_RESET
|
INIT_FUNC_WATCHDOG_RESET
|
||||||
initr_net,
|
initr_net,
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -423,7 +423,7 @@ static int usb_kbd_testc(struct stdio_dev *sdev)
|
||||||
*/
|
*/
|
||||||
unsigned long poll_delay = CONFIG_SYS_HZ / 50;
|
unsigned long poll_delay = CONFIG_SYS_HZ / 50;
|
||||||
|
|
||||||
#ifdef CONFIG_CMD_NET
|
#if defined(CONFIG_CMD_NET) && !defined(CONFIG_NET_LWIP)
|
||||||
/*
|
/*
|
||||||
* If net_busy_flag is 1, NET transfer is running,
|
* If net_busy_flag is 1, NET transfer is running,
|
||||||
* then we check key-pressed every second (first check may be
|
* then we check key-pressed every second (first check may be
|
||||||
|
|
|
@ -97,7 +97,7 @@ config DSA_SANDBOX
|
||||||
|
|
||||||
menuconfig NETDEVICES
|
menuconfig NETDEVICES
|
||||||
bool "Network device support"
|
bool "Network device support"
|
||||||
depends on NET
|
depends on NET || NET_LWIP
|
||||||
select DM_ETH
|
select DM_ETH
|
||||||
help
|
help
|
||||||
You must select Y to enable any network device support
|
You must select Y to enable any network device support
|
||||||
|
|
|
@ -118,6 +118,9 @@ extern int net_restart_wrap; /* Tried all network devices */
|
||||||
extern uchar *net_rx_packets[PKTBUFSRX]; /* Receive packets */
|
extern uchar *net_rx_packets[PKTBUFSRX]; /* Receive packets */
|
||||||
extern const u8 net_bcast_ethaddr[ARP_HLEN]; /* Ethernet broadcast address */
|
extern const u8 net_bcast_ethaddr[ARP_HLEN]; /* Ethernet broadcast address */
|
||||||
extern char net_boot_file_name[1024];/* Boot File name */
|
extern char net_boot_file_name[1024];/* Boot File name */
|
||||||
|
extern struct in_addr net_ip; /* Our IP addr (0 = unknown) */
|
||||||
|
/* Indicates whether the pxe path prefix / config file was specified in dhcp option */
|
||||||
|
extern char *pxelinux_configfile;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* compute_ip_checksum() - Compute IP checksum
|
* compute_ip_checksum() - Compute IP checksum
|
||||||
|
|
|
@ -285,12 +285,9 @@ extern char net_hostname[32]; /* Our hostname */
|
||||||
#ifdef CONFIG_NET
|
#ifdef CONFIG_NET
|
||||||
extern char net_root_path[CONFIG_BOOTP_MAX_ROOT_PATH_LEN]; /* Our root path */
|
extern char net_root_path[CONFIG_BOOTP_MAX_ROOT_PATH_LEN]; /* Our root path */
|
||||||
#endif
|
#endif
|
||||||
/* Indicates whether the pxe path prefix / config file was specified in dhcp option */
|
|
||||||
extern char *pxelinux_configfile;
|
|
||||||
/** END OF BOOTP EXTENTIONS **/
|
/** END OF BOOTP EXTENTIONS **/
|
||||||
extern u8 net_ethaddr[ARP_HLEN]; /* Our ethernet address */
|
extern u8 net_ethaddr[ARP_HLEN]; /* Our ethernet address */
|
||||||
extern u8 net_server_ethaddr[ARP_HLEN]; /* Boot server enet address */
|
extern u8 net_server_ethaddr[ARP_HLEN]; /* Boot server enet address */
|
||||||
extern struct in_addr net_ip; /* Our IP addr (0 = unknown) */
|
|
||||||
extern struct in_addr net_server_ip; /* Server IP addr (0 = unknown) */
|
extern struct in_addr net_server_ip; /* Server IP addr (0 = unknown) */
|
||||||
extern uchar *net_tx_packet; /* THE transmit packet */
|
extern uchar *net_tx_packet; /* THE transmit packet */
|
||||||
extern uchar *net_rx_packets[PKTBUFSRX]; /* Receive packets */
|
extern uchar *net_rx_packets[PKTBUFSRX]; /* Receive packets */
|
||||||
|
|
|
@ -10,5 +10,8 @@ struct netif *net_lwip_new_netif(struct udevice *udev);
|
||||||
struct netif *net_lwip_new_netif_noip(struct udevice *udev);
|
struct netif *net_lwip_new_netif_noip(struct udevice *udev);
|
||||||
void net_lwip_remove_netif(struct netif *netif);
|
void net_lwip_remove_netif(struct netif *netif);
|
||||||
struct netif *net_lwip_get_netif(void);
|
struct netif *net_lwip_get_netif(void);
|
||||||
|
int net_lwip_rx(struct udevice *udev, struct netif *netif);
|
||||||
|
|
||||||
|
int do_dhcp(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
|
||||||
|
|
||||||
#endif /* __NET_LWIP_H__ */
|
#endif /* __NET_LWIP_H__ */
|
||||||
|
|
|
@ -269,7 +269,8 @@ static int _vprintf(struct printf_info *info, const char *fmt, va_list va)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'p':
|
case 'p':
|
||||||
if (CONFIG_IS_ENABLED(NET) || _DEBUG) {
|
if (CONFIG_IS_ENABLED(NET) ||
|
||||||
|
CONFIG_IS_ENABLED(NET_LWIP) || _DEBUG) {
|
||||||
pointer(info, fmt, va_arg(va, void *));
|
pointer(info, fmt, va_arg(va, void *));
|
||||||
/*
|
/*
|
||||||
* Skip this because it pulls in _ctype which is
|
* Skip this because it pulls in _ctype which is
|
||||||
|
|
14
net/Makefile
14
net/Makefile
|
@ -12,11 +12,6 @@ obj-$(CONFIG_CMD_BOOTP) += bootp.o
|
||||||
obj-$(CONFIG_CMD_CDP) += cdp.o
|
obj-$(CONFIG_CMD_CDP) += cdp.o
|
||||||
obj-$(CONFIG_CMD_DNS) += dns.o
|
obj-$(CONFIG_CMD_DNS) += dns.o
|
||||||
obj-$(CONFIG_DM_DSA) += dsa-uclass.o
|
obj-$(CONFIG_DM_DSA) += dsa-uclass.o
|
||||||
obj-$(CONFIG_$(XPL_)DM_ETH) += eth-uclass.o
|
|
||||||
obj-$(CONFIG_$(PHASE_)BOOTDEV_ETH) += eth_bootdev.o
|
|
||||||
obj-$(CONFIG_DM_MDIO) += mdio-uclass.o
|
|
||||||
obj-$(CONFIG_DM_MDIO_MUX) += mdio-mux-uclass.o
|
|
||||||
obj-$(CONFIG_$(XPL_)DM_ETH) += eth_common.o
|
|
||||||
obj-$(CONFIG_CMD_LINK_LOCAL) += link_local.o
|
obj-$(CONFIG_CMD_LINK_LOCAL) += link_local.o
|
||||||
obj-$(CONFIG_IPV6) += ndisc.o
|
obj-$(CONFIG_IPV6) += ndisc.o
|
||||||
obj-$(CONFIG_$(XPL_)DM_ETH) += net.o
|
obj-$(CONFIG_$(XPL_)DM_ETH) += net.o
|
||||||
|
@ -43,4 +38,13 @@ CFLAGS_eth_common.o += -Wno-format-extra-args
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(filter y,$(CONFIG_NET) $(CONFIG_NET_LWIP)),y)
|
||||||
|
obj-$(CONFIG_$(XPL_)DM_ETH) += eth-uclass.o
|
||||||
|
obj-$(CONFIG_$(PHASE_)BOOTDEV_ETH) += eth_bootdev.o
|
||||||
|
obj-$(CONFIG_DM_MDIO) += mdio-uclass.o
|
||||||
|
obj-$(CONFIG_DM_MDIO_MUX) += mdio-mux-uclass.o
|
||||||
|
obj-$(CONFIG_$(XPL_)DM_ETH) += eth_common.o
|
||||||
obj-y += net-common.o
|
obj-y += net-common.o
|
||||||
|
endif
|
||||||
|
|
||||||
|
obj-$(CONFIG_NET_LWIP) += lwip/
|
||||||
|
|
5
net/lwip/Makefile
Normal file
5
net/lwip/Makefile
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
ccflags-y += -I$(srctree)/lib/lwip/lwip/src/include -I$(srctree)/lib/lwip/u-boot
|
||||||
|
|
||||||
|
obj-$(CONFIG_$(SPL_)DM_ETH) += net-lwip.o
|
||||||
|
obj-$(CONFIG_CMD_DHCP) += dhcp.o
|
||||||
|
obj-$(CONFIG_CMD_TFTPBOOT) += tftp.o
|
130
net/lwip/dhcp.c
Normal file
130
net/lwip/dhcp.c
Normal file
|
@ -0,0 +1,130 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0+
|
||||||
|
/* Copyright (C) 2024 Linaro Ltd. */
|
||||||
|
|
||||||
|
#include <command.h>
|
||||||
|
#include <console.h>
|
||||||
|
#include <dm/device.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/errno.h>
|
||||||
|
#include <lwip/dhcp.h>
|
||||||
|
#include <lwip/dns.h>
|
||||||
|
#include <lwip/timeouts.h>
|
||||||
|
#include <net.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#define DHCP_TIMEOUT_MS 10000
|
||||||
|
|
||||||
|
#ifdef CONFIG_CMD_TFTPBOOT
|
||||||
|
/* Boot file obtained from DHCP (if present) */
|
||||||
|
static char boot_file_name[DHCP_BOOT_FILE_LEN];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void call_lwip_dhcp_fine_tmr(void *ctx)
|
||||||
|
{
|
||||||
|
dhcp_fine_tmr();
|
||||||
|
sys_timeout(10, call_lwip_dhcp_fine_tmr, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dhcp_loop(struct udevice *udev)
|
||||||
|
{
|
||||||
|
char *ipstr = "ipaddr\0\0";
|
||||||
|
char *maskstr = "netmask\0\0";
|
||||||
|
char *gwstr = "gatewayip\0\0";
|
||||||
|
unsigned long start;
|
||||||
|
struct netif *netif;
|
||||||
|
struct dhcp *dhcp;
|
||||||
|
bool bound;
|
||||||
|
int idx;
|
||||||
|
|
||||||
|
idx = dev_seq(udev);
|
||||||
|
if (idx < 0 || idx > 99) {
|
||||||
|
log_err("unexpected idx %d\n", idx);
|
||||||
|
return CMD_RET_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
netif = net_lwip_new_netif_noip(udev);
|
||||||
|
if (!netif)
|
||||||
|
return CMD_RET_FAILURE;
|
||||||
|
|
||||||
|
start = get_timer(0);
|
||||||
|
|
||||||
|
if (dhcp_start(netif))
|
||||||
|
return CMD_RET_FAILURE;
|
||||||
|
|
||||||
|
call_lwip_dhcp_fine_tmr(NULL);
|
||||||
|
|
||||||
|
/* Wait for DHCP to complete */
|
||||||
|
do {
|
||||||
|
net_lwip_rx(udev, netif);
|
||||||
|
sys_check_timeouts();
|
||||||
|
bound = dhcp_supplied_address(netif);
|
||||||
|
if (bound)
|
||||||
|
break;
|
||||||
|
if (ctrlc()) {
|
||||||
|
printf("Abort\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
mdelay(1);
|
||||||
|
} while (get_timer(start) < DHCP_TIMEOUT_MS);
|
||||||
|
|
||||||
|
sys_untimeout(call_lwip_dhcp_fine_tmr, NULL);
|
||||||
|
|
||||||
|
if (!bound) {
|
||||||
|
net_lwip_remove_netif(netif);
|
||||||
|
return CMD_RET_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
dhcp = netif_dhcp_data(netif);
|
||||||
|
|
||||||
|
env_set("bootfile", dhcp->boot_file_name);
|
||||||
|
|
||||||
|
if (idx > 0) {
|
||||||
|
sprintf(ipstr, "ipaddr%d", idx);
|
||||||
|
sprintf(maskstr, "netmask%d", idx);
|
||||||
|
sprintf(gwstr, "gatewayip%d", idx);
|
||||||
|
} else {
|
||||||
|
net_ip.s_addr = dhcp->offered_ip_addr.addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
env_set(ipstr, ip4addr_ntoa(&dhcp->offered_ip_addr));
|
||||||
|
env_set(maskstr, ip4addr_ntoa(&dhcp->offered_sn_mask));
|
||||||
|
env_set("serverip", ip4addr_ntoa(&dhcp->server_ip_addr));
|
||||||
|
if (dhcp->offered_gw_addr.addr != 0)
|
||||||
|
env_set(gwstr, ip4addr_ntoa(&dhcp->offered_gw_addr));
|
||||||
|
|
||||||
|
#ifdef CONFIG_PROT_DNS_LWIP
|
||||||
|
env_set("dnsip", ip4addr_ntoa(dns_getserver(0)));
|
||||||
|
env_set("dnsip2", ip4addr_ntoa(dns_getserver(1)));
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_CMD_TFTPBOOT
|
||||||
|
if (dhcp->boot_file_name[0] != '\0')
|
||||||
|
strncpy(boot_file_name, dhcp->boot_file_name,
|
||||||
|
sizeof(boot_file_name));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
printf("DHCP client bound to address %pI4 (%lu ms)\n",
|
||||||
|
&dhcp->offered_ip_addr, get_timer(start));
|
||||||
|
|
||||||
|
net_lwip_remove_netif(netif);
|
||||||
|
return CMD_RET_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int do_dhcp(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
|
||||||
|
{
|
||||||
|
eth_set_current();
|
||||||
|
|
||||||
|
return dhcp_loop(eth_get_dev());
|
||||||
|
}
|
||||||
|
|
||||||
|
int dhcp_run(ulong addr, const char *fname, bool autoload)
|
||||||
|
{
|
||||||
|
char *dhcp_argv[] = {"dhcp", NULL, };
|
||||||
|
struct cmd_tbl cmdtp = {}; /* dummy */
|
||||||
|
|
||||||
|
if (autoload) {
|
||||||
|
/* Will be supported when TFTP is added */
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
|
||||||
|
return do_dhcp(&cmdtp, 0, 1, dhcp_argv);
|
||||||
|
}
|
35
net/lwip/eth_internal.h
Normal file
35
net/lwip/eth_internal.h
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||||
|
/*
|
||||||
|
* (C) Copyright 2001-2015
|
||||||
|
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||||
|
* Joe Hershberger, National Instruments
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ETH_INTERNAL_H
|
||||||
|
#define __ETH_INTERNAL_H
|
||||||
|
|
||||||
|
/* Do init that is common to driver model and legacy networking */
|
||||||
|
void eth_common_init(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* eth_env_set_enetaddr_by_index() - set the MAC address environment variable
|
||||||
|
*
|
||||||
|
* This sets up an environment variable with the given MAC address (@enetaddr).
|
||||||
|
* The environment variable to be set is defined by <@base_name><@index>addr.
|
||||||
|
* If @index is 0 it is omitted. For common Ethernet this means ethaddr,
|
||||||
|
* eth1addr, etc.
|
||||||
|
*
|
||||||
|
* @base_name: Base name for variable, typically "eth"
|
||||||
|
* @index: Index of interface being updated (>=0)
|
||||||
|
* @enetaddr: Pointer to MAC address to put into the variable
|
||||||
|
* Return: 0 if OK, other value on error
|
||||||
|
*/
|
||||||
|
int eth_env_set_enetaddr_by_index(const char *base_name, int index,
|
||||||
|
uchar *enetaddr);
|
||||||
|
|
||||||
|
int eth_mac_skip(int index);
|
||||||
|
void eth_current_changed(void);
|
||||||
|
void eth_set_dev(struct udevice *dev);
|
||||||
|
void eth_set_current_to_next(void);
|
||||||
|
|
||||||
|
#endif
|
289
net/lwip/net-lwip.c
Normal file
289
net/lwip/net-lwip.c
Normal file
|
@ -0,0 +1,289 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
|
|
||||||
|
/* Copyright (C) 2024 Linaro Ltd. */
|
||||||
|
|
||||||
|
#include <command.h>
|
||||||
|
#include <dm/device.h>
|
||||||
|
#include <dm/uclass.h>
|
||||||
|
#include <lwip/ip4_addr.h>
|
||||||
|
#include <lwip/err.h>
|
||||||
|
#include <lwip/netif.h>
|
||||||
|
#include <lwip/pbuf.h>
|
||||||
|
#include <lwip/etharp.h>
|
||||||
|
#include <lwip/init.h>
|
||||||
|
#include <lwip/prot/etharp.h>
|
||||||
|
#include <net.h>
|
||||||
|
|
||||||
|
/* xx:xx:xx:xx:xx:xx\0 */
|
||||||
|
#define MAC_ADDR_STRLEN 18
|
||||||
|
|
||||||
|
#if defined(CONFIG_API) || defined(CONFIG_EFI_LOADER)
|
||||||
|
void (*push_packet)(void *, int len) = 0;
|
||||||
|
#endif
|
||||||
|
int net_restart_wrap;
|
||||||
|
static uchar net_pkt_buf[(PKTBUFSRX) * PKTSIZE_ALIGN + PKTALIGN];
|
||||||
|
uchar *net_rx_packets[PKTBUFSRX];
|
||||||
|
uchar *net_rx_packet;
|
||||||
|
const u8 net_bcast_ethaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||||
|
char *pxelinux_configfile;
|
||||||
|
/* Our IP addr (0 = unknown) */
|
||||||
|
struct in_addr net_ip;
|
||||||
|
|
||||||
|
static err_t linkoutput(struct netif *netif, struct pbuf *p)
|
||||||
|
{
|
||||||
|
struct udevice *udev = netif->state;
|
||||||
|
void *pp = NULL;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if ((unsigned long)p->payload % PKTALIGN) {
|
||||||
|
/*
|
||||||
|
* Some net drivers have strict alignment requirements and may
|
||||||
|
* fail or output invalid data if the packet is not aligned.
|
||||||
|
*/
|
||||||
|
pp = memalign(PKTALIGN, p->len);
|
||||||
|
if (!pp)
|
||||||
|
return ERR_ABRT;
|
||||||
|
memcpy(pp, p->payload, p->len);
|
||||||
|
}
|
||||||
|
|
||||||
|
err = eth_get_ops(udev)->send(udev, pp ? pp : p->payload, p->len);
|
||||||
|
free(pp);
|
||||||
|
if (err) {
|
||||||
|
log_err("send error %d\n", err);
|
||||||
|
return ERR_ABRT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static err_t net_lwip_if_init(struct netif *netif)
|
||||||
|
{
|
||||||
|
netif->output = etharp_output;
|
||||||
|
netif->linkoutput = linkoutput;
|
||||||
|
netif->mtu = 1500;
|
||||||
|
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;
|
||||||
|
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void eth_init_rings(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < PKTBUFSRX; i++)
|
||||||
|
net_rx_packets[i] = net_pkt_buf + i * PKTSIZE_ALIGN;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct netif *net_lwip_get_netif(void)
|
||||||
|
{
|
||||||
|
struct netif *netif, *found = NULL;
|
||||||
|
|
||||||
|
NETIF_FOREACH(netif) {
|
||||||
|
if (!found)
|
||||||
|
found = netif;
|
||||||
|
else
|
||||||
|
printf("Error: more than one netif in lwIP\n");
|
||||||
|
}
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_udev_ipv4_info(struct udevice *dev, ip4_addr_t *ip,
|
||||||
|
ip4_addr_t *mask, ip4_addr_t *gw)
|
||||||
|
{
|
||||||
|
char *ipstr = "ipaddr\0\0";
|
||||||
|
char *maskstr = "netmask\0\0";
|
||||||
|
char *gwstr = "gatewayip\0\0";
|
||||||
|
int idx = dev_seq(dev);
|
||||||
|
char *env;
|
||||||
|
|
||||||
|
if (idx < 0 || idx > 99) {
|
||||||
|
log_err("unexpected idx %d\n", idx);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (idx) {
|
||||||
|
sprintf(ipstr, "ipaddr%d", idx);
|
||||||
|
sprintf(maskstr, "netmask%d", idx);
|
||||||
|
sprintf(gwstr, "gatewayip%d", idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
ip4_addr_set_zero(ip);
|
||||||
|
ip4_addr_set_zero(mask);
|
||||||
|
ip4_addr_set_zero(gw);
|
||||||
|
|
||||||
|
env = env_get(ipstr);
|
||||||
|
if (env)
|
||||||
|
ip4addr_aton(env, ip);
|
||||||
|
|
||||||
|
env = env_get(maskstr);
|
||||||
|
if (env)
|
||||||
|
ip4addr_aton(env, mask);
|
||||||
|
|
||||||
|
env = env_get(gwstr);
|
||||||
|
if (env)
|
||||||
|
ip4addr_aton(env, gw);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct netif *new_netif(struct udevice *udev, bool with_ip)
|
||||||
|
{
|
||||||
|
unsigned char enetaddr[ARP_HLEN];
|
||||||
|
char hwstr[MAC_ADDR_STRLEN];
|
||||||
|
ip4_addr_t ip, mask, gw;
|
||||||
|
struct netif *netif;
|
||||||
|
int ret = 0;
|
||||||
|
static bool first_call = true;
|
||||||
|
|
||||||
|
if (!udev)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (first_call) {
|
||||||
|
eth_init_rings();
|
||||||
|
/* Pick a valid active device, if any */
|
||||||
|
eth_init();
|
||||||
|
lwip_init();
|
||||||
|
first_call = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (eth_start_udev(udev) < 0) {
|
||||||
|
log_err("Could not start %s\n", udev->name);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
netif_remove(net_lwip_get_netif());
|
||||||
|
|
||||||
|
ip4_addr_set_zero(&ip);
|
||||||
|
ip4_addr_set_zero(&mask);
|
||||||
|
ip4_addr_set_zero(&gw);
|
||||||
|
|
||||||
|
if (with_ip)
|
||||||
|
if (get_udev_ipv4_info(udev, &ip, &mask, &gw) < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
eth_env_get_enetaddr_by_index("eth", dev_seq(udev), enetaddr);
|
||||||
|
ret = snprintf(hwstr, MAC_ADDR_STRLEN, "%pM", enetaddr);
|
||||||
|
if (ret < 0 || ret >= MAC_ADDR_STRLEN)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
netif = calloc(1, sizeof(struct netif));
|
||||||
|
if (!netif)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
netif->name[0] = 'e';
|
||||||
|
netif->name[1] = 't';
|
||||||
|
|
||||||
|
string_to_enetaddr(hwstr, netif->hwaddr);
|
||||||
|
netif->hwaddr_len = ETHARP_HWADDR_LEN;
|
||||||
|
debug("adding lwIP netif for %s with hwaddr:%s ip:%s ", udev->name,
|
||||||
|
hwstr, ip4addr_ntoa(&ip));
|
||||||
|
debug("mask:%s ", ip4addr_ntoa(&mask));
|
||||||
|
debug("gw:%s\n", ip4addr_ntoa(&gw));
|
||||||
|
|
||||||
|
if (!netif_add(netif, &ip, &mask, &gw, udev, net_lwip_if_init,
|
||||||
|
netif_input)) {
|
||||||
|
printf("error: netif_add() failed\n");
|
||||||
|
free(netif);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
netif_set_up(netif);
|
||||||
|
netif_set_link_up(netif);
|
||||||
|
/* Routing: use this interface to reach the default gateway */
|
||||||
|
netif_set_default(netif);
|
||||||
|
|
||||||
|
return netif;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct netif *net_lwip_new_netif(struct udevice *udev)
|
||||||
|
{
|
||||||
|
return new_netif(udev, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct netif *net_lwip_new_netif_noip(struct udevice *udev)
|
||||||
|
{
|
||||||
|
|
||||||
|
return new_netif(udev, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void net_lwip_remove_netif(struct netif *netif)
|
||||||
|
{
|
||||||
|
netif_remove(netif);
|
||||||
|
free(netif);
|
||||||
|
}
|
||||||
|
|
||||||
|
int net_init(void)
|
||||||
|
{
|
||||||
|
eth_set_current();
|
||||||
|
|
||||||
|
net_lwip_new_netif(eth_get_dev());
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct pbuf *alloc_pbuf_and_copy(uchar *data, int len)
|
||||||
|
{
|
||||||
|
struct pbuf *p, *q;
|
||||||
|
|
||||||
|
/* We allocate a pbuf chain of pbufs from the pool. */
|
||||||
|
p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
|
||||||
|
if (!p) {
|
||||||
|
LINK_STATS_INC(link.memerr);
|
||||||
|
LINK_STATS_INC(link.drop);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (q = p; q != NULL; q = q->next) {
|
||||||
|
memcpy(q->payload, data, q->len);
|
||||||
|
data += q->len;
|
||||||
|
}
|
||||||
|
|
||||||
|
LINK_STATS_INC(link.recv);
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
int net_lwip_rx(struct udevice *udev, struct netif *netif)
|
||||||
|
{
|
||||||
|
struct pbuf *pbuf;
|
||||||
|
uchar *packet;
|
||||||
|
int flags;
|
||||||
|
int len;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!eth_is_active(udev))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
flags = ETH_RECV_CHECK_DEVICE;
|
||||||
|
for (i = 0; i < ETH_PACKETS_BATCH_RECV; i++) {
|
||||||
|
len = eth_get_ops(udev)->recv(udev, flags, &packet);
|
||||||
|
flags = 0;
|
||||||
|
|
||||||
|
if (len > 0) {
|
||||||
|
pbuf = alloc_pbuf_and_copy(packet, len);
|
||||||
|
if (pbuf)
|
||||||
|
netif->input(pbuf, netif);
|
||||||
|
}
|
||||||
|
if (len >= 0 && eth_get_ops(udev)->free_pkt)
|
||||||
|
eth_get_ops(udev)->free_pkt(udev, packet, len);
|
||||||
|
if (len <= 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (len == -EAGAIN)
|
||||||
|
len = 0;
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
void net_process_received_packet(uchar *in_packet, int len)
|
||||||
|
{
|
||||||
|
#if defined(CONFIG_API) || defined(CONFIG_EFI_LOADER)
|
||||||
|
if (push_packet)
|
||||||
|
(*push_packet)(in_packet, len);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
u32_t sys_now(void)
|
||||||
|
{
|
||||||
|
return get_timer(0);
|
||||||
|
}
|
11
net/lwip/tftp.c
Normal file
11
net/lwip/tftp.c
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0+
|
||||||
|
/* Copyright (C) 2024 Linaro Ltd. */
|
||||||
|
|
||||||
|
#include <command.h>
|
||||||
|
#include <net-lwip.h>
|
||||||
|
|
||||||
|
int do_tftpb(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
|
||||||
|
{
|
||||||
|
/* Not implemented */
|
||||||
|
return CMD_RET_FAILURE;
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue