
On Wed, 16 Oct 2024 at 13:04, Jerome Forissier jerome.forissier@linaro.org wrote:
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
board/engicam/imx8mp/icore_mx8mp.c | 2 +- .../imx8mp_debix_model_a.c | 2 +- board/ti/am335x/board.c | 3 +- board/xilinx/common/board.c | 3 +- cmd/Kconfig | 100 +++--- cmd/Makefile | 6 +- cmd/elf.c | 2 +- cmd/net-lwip.c | 13 + common/board_r.c | 4 +- common/usb_kbd.c | 2 +- drivers/net/Kconfig | 2 +- include/net-common.h | 3 + include/net-legacy.h | 3 - include/net-lwip.h | 3 + lib/tiny-printf.c | 3 +- net/Makefile | 14 +- net/lwip/Makefile | 5 + net/lwip/dhcp.c | 130 ++++++++ net/lwip/eth_internal.h | 35 +++ net/lwip/net-lwip.c | 289 ++++++++++++++++++ net/lwip/tftp.c | 11 + 21 files changed, 573 insertions(+), 62 deletions(-) create mode 100644 cmd/net-lwip.c create mode 100644 net/lwip/Makefile create mode 100644 net/lwip/dhcp.c create mode 100644 net/lwip/eth_internal.h create mode 100644 net/lwip/net-lwip.c create mode 100644 net/lwip/tftp.c
diff --git a/board/engicam/imx8mp/icore_mx8mp.c b/board/engicam/imx8mp/icore_mx8mp.c index e2ed70caa43..bfdc447c478 100644 --- a/board/engicam/imx8mp/icore_mx8mp.c +++ b/board/engicam/imx8mp/icore_mx8mp.c @@ -33,7 +33,7 @@ static void setup_fec(void) 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) { if (phydev->drv->config) diff --git a/board/polyhex/imx8mp_debix_model_a/imx8mp_debix_model_a.c b/board/polyhex/imx8mp_debix_model_a/imx8mp_debix_model_a.c index 112770ba493..c709d017483 100644 --- a/board/polyhex/imx8mp_debix_model_a/imx8mp_debix_model_a.c +++ b/board/polyhex/imx8mp_debix_model_a/imx8mp_debix_model_a.c @@ -29,7 +29,7 @@ static void setup_fec(void) 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) { if (phydev->drv->config) diff --git a/board/ti/am335x/board.c b/board/ti/am335x/board.c index 720bf2cb3e1..774ef7ac5e3 100644 --- a/board/ti/am335x/board.c +++ b/board/ti/am335x/board.c @@ -900,7 +900,8 @@ int board_late_init(void) #endif
/* 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[] = { { .slave_reg_ofs = CPSW_SLAVE0_OFFSET, diff --git a/board/xilinx/common/board.c b/board/xilinx/common/board.c index 68f401e4b34..38dd80533fa 100644 --- a/board/xilinx/common/board.c +++ b/board/xilinx/common/board.c @@ -491,7 +491,8 @@ int board_late_init_xilinx(void) ret |= env_set_by_index("uuid", id, uuid); }
if (!CONFIG_IS_ENABLED(NET))
if (!(CONFIG_IS_ENABLED(NET) ||
CONFIG_IS_ENABLED(NET_LWIP))) continue; for (i = 0; i < EEPROM_HDR_NO_OF_MAC_ADDR; i++) {
diff --git a/cmd/Kconfig b/cmd/Kconfig index 6d20d7597cb..211be398937 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -1789,12 +1789,16 @@ config CMD_AB_SELECT
endmenu
-if NET +if NET || NET_LWIP
menuconfig CMD_NET bool "Network commands" default y
+endif
+if NET
if CMD_NET
config CMD_BOOTP @@ -1803,12 +1807,6 @@ config CMD_BOOTP help 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 bool "dhcp6" depends on IPV6 @@ -1952,12 +1950,6 @@ config BOOTP_VCI_STRING default "U-Boot.arm" if ARM default "U-Boot"
-config CMD_TFTPBOOT
bool "tftpboot"
default y
help
tftpboot - load file via network using TFTP protocol
config CMD_TFTPPUT bool "tftp put" depends on CMD_TFTPBOOT @@ -2017,29 +2009,6 @@ config CMD_WGET wget is a simple command to download kernel, or other files, 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 bool "ping" help @@ -2088,7 +2057,7 @@ config IPV6_ROUTER_DISCOVERY help Will automatically perform router solicitation on first IPv6 network operation -endif +endif # if CMD_NET
config CMD_ETHSW bool "ethsw" @@ -2098,6 +2067,56 @@ config CMD_ETHSW operations such as enabling / disabling a port and 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 bool "pxe" select PXE_UTILS @@ -2105,12 +2124,7 @@ config CMD_PXE help Boot image via network using PXE protocol
-config CMD_WOL
bool "wol"
help
Wait for wake-on-lan Magic Packet
-endif +endif # if NET || NET_LWIP
menu "Misc commands"
diff --git a/cmd/Makefile b/cmd/Makefile index 21d376309b9..94a3df41c6f 100644 --- a/cmd/Makefile +++ b/cmd/Makefile @@ -127,7 +127,11 @@ obj-y += legacy-mtd-utils.o endif obj-$(CONFIG_CMD_MUX) += mux.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_CMD_NVEDIT_EFI) += nvedit_efi.o obj-$(CONFIG_CMD_ONENAND) += onenand.o diff --git a/cmd/elf.c b/cmd/elf.c index 114f2caf7fa..6b49c613703 100644 --- a/cmd/elf.c +++ b/cmd/elf.c @@ -133,7 +133,7 @@ int do_bootvx(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) else 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 * before starting diff --git a/cmd/net-lwip.c b/cmd/net-lwip.c new file mode 100644 index 00000000000..82edb5fd2e6 --- /dev/null +++ b/cmd/net-lwip.c @@ -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 diff --git a/common/board_r.c b/common/board_r.c index 1acad069d92..e5f33f40643 100644 --- a/common/board_r.c +++ b/common/board_r.c @@ -484,7 +484,7 @@ static int initr_boot_led_on(void) return 0; }
-#ifdef CONFIG_CMD_NET +#if defined(CONFIG_CMD_NET) static int initr_net(void) { puts("Net: "); @@ -749,7 +749,7 @@ static init_fnc_t init_sequence_r[] = { #ifdef CONFIG_PCI_ENDPOINT pci_ep_init, #endif -#ifdef CONFIG_CMD_NET +#if defined(CONFIG_CMD_NET) INIT_FUNC_WATCHDOG_RESET initr_net, #endif diff --git a/common/usb_kbd.c b/common/usb_kbd.c index bbfee23bc26..36107a3b278 100644 --- a/common/usb_kbd.c +++ b/common/usb_kbd.c @@ -423,7 +423,7 @@ static int usb_kbd_testc(struct stdio_dev *sdev) */ 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, * then we check key-pressed every second (first check may be diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index fa6fc1cb8e4..89f7411bdf3 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -97,7 +97,7 @@ config DSA_SANDBOX
menuconfig NETDEVICES bool "Network device support"
depends on NET
depends on NET || NET_LWIP select DM_ETH help You must select Y to enable any network device support
diff --git a/include/net-common.h b/include/net-common.h index 6bc76658d9d..cbcac178c82 100644 --- a/include/net-common.h +++ b/include/net-common.h @@ -118,6 +118,9 @@ extern int net_restart_wrap; /* Tried all network devices */ extern uchar *net_rx_packets[PKTBUFSRX]; /* Receive packets */ extern const u8 net_bcast_ethaddr[ARP_HLEN]; /* Ethernet broadcast address */ 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
diff --git a/include/net-legacy.h b/include/net-legacy.h index ed286e3d326..ca1efd17af7 100644 --- a/include/net-legacy.h +++ b/include/net-legacy.h @@ -285,12 +285,9 @@ extern char net_hostname[32]; /* Our hostname */ #ifdef CONFIG_NET extern char net_root_path[CONFIG_BOOTP_MAX_ROOT_PATH_LEN]; /* Our root path */ #endif -/* Indicates whether the pxe path prefix / config file was specified in dhcp option */ -extern char *pxelinux_configfile; /** END OF BOOTP EXTENTIONS **/ extern u8 net_ethaddr[ARP_HLEN]; /* Our ethernet 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 uchar *net_tx_packet; /* THE transmit packet */ extern uchar *net_rx_packets[PKTBUFSRX]; /* Receive packets */ diff --git a/include/net-lwip.h b/include/net-lwip.h index 5c3f9e7e86c..cfd06726577 100644 --- a/include/net-lwip.h +++ b/include/net-lwip.h @@ -10,5 +10,8 @@ struct netif *net_lwip_new_netif(struct udevice *udev); struct netif *net_lwip_new_netif_noip(struct udevice *udev); void net_lwip_remove_netif(struct netif *netif); 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__ */ diff --git a/lib/tiny-printf.c b/lib/tiny-printf.c index 64dee779c4a..cc1dfe61cf7 100644 --- a/lib/tiny-printf.c +++ b/lib/tiny-printf.c @@ -269,7 +269,8 @@ static int _vprintf(struct printf_info *info, const char *fmt, va_list va) } break; 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 *)); /* * Skip this because it pulls in _ctype which is
diff --git a/net/Makefile b/net/Makefile index 34fe50133a3..209377aeb26 100644 --- a/net/Makefile +++ b/net/Makefile @@ -12,11 +12,6 @@ obj-$(CONFIG_CMD_BOOTP) += bootp.o obj-$(CONFIG_CMD_CDP) += cdp.o obj-$(CONFIG_CMD_DNS) += dns.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_IPV6) += ndisc.o obj-$(CONFIG_$(XPL_)DM_ETH) += net.o @@ -43,4 +38,13 @@ CFLAGS_eth_common.o += -Wno-format-extra-args
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 +endif
+obj-$(CONFIG_NET_LWIP) += lwip/ diff --git a/net/lwip/Makefile b/net/lwip/Makefile new file mode 100644 index 00000000000..4e92a101ddb --- /dev/null +++ b/net/lwip/Makefile @@ -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 diff --git a/net/lwip/dhcp.c b/net/lwip/dhcp.c new file mode 100644 index 00000000000..a2cc25d88f5 --- /dev/null +++ b/net/lwip/dhcp.c @@ -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);
+} diff --git a/net/lwip/eth_internal.h b/net/lwip/eth_internal.h new file mode 100644 index 00000000000..0b829a8d388 --- /dev/null +++ b/net/lwip/eth_internal.h @@ -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 diff --git a/net/lwip/net-lwip.c b/net/lwip/net-lwip.c new file mode 100644 index 00000000000..3b08ffe3b74 --- /dev/null +++ b/net/lwip/net-lwip.c @@ -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);
+} diff --git a/net/lwip/tftp.c b/net/lwip/tftp.c new file mode 100644 index 00000000000..1fa246f55d9 --- /dev/null +++ b/net/lwip/tftp.c @@ -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;
+}
2.40.1
Acked-by: Ilias Apalodimas ilias.apalodimas@linaro.org