On Wed, 16 Oct 2024 at 13:04, Jerome Forissier <jerome.foriss...@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.foriss...@linaro.org> > Tested-by: Ilias Apalodimas <ilias.apalodi...@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, w...@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.apalodi...@linaro.org>