summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2019-09-04 16:02:03 -0400
committerTom Rini <trini@konsulko.com>2019-09-04 16:02:03 -0400
commitece9834f7d223097cec92e3d3c70cd37b3768482 (patch)
treed2935e582cb3494364bf2b7bc89a3d227d616e97
parent448f11f7503995746a7b71e5e3b3a831c4651be9 (diff)
parent5a5d1def59024dd3225e2a6142f8ee3ee10180a8 (diff)
downloadu-boot-WIP/04Sep2019.tar.gz
Merge branch 'master' of https://gitlab.denx.de/u-boot/custodians/u-boot-netWIP/04Sep2019
- Assorted CVE fixes - Other fixes
-rw-r--r--Makefile11
-rw-r--r--arch/arm/cpu/armv8/fsl-layerscape/Kconfig17
-rw-r--r--arch/arm/dts/armada-cp110-master.dtsi1
-rw-r--r--arch/arm/dts/armada-cp110-slave.dtsi1
-rw-r--r--board/st/stm32mp1/stm32mp1.c16
-rw-r--r--cmd/Kconfig7
-rw-r--r--cmd/Makefile1
-rw-r--r--cmd/mdio.c3
-rw-r--r--cmd/pcap.c71
-rw-r--r--configs/sandbox_defconfig1
-rw-r--r--doc/README.pcap62
-rw-r--r--doc/device-tree-bindings/net/marvell-mdio.txt15
-rw-r--r--doc/device-tree-bindings/net/mdio.txt36
-rw-r--r--doc/driver-model/migration.rst8
-rw-r--r--drivers/net/Kconfig11
-rw-r--r--drivers/net/Makefile1
-rw-r--r--drivers/net/designware.c1
-rw-r--r--drivers/net/dwc_eth_qos.c28
-rw-r--r--drivers/net/fsl-mc/Kconfig25
-rw-r--r--drivers/net/fsl_enetc_mdio.c1
-rw-r--r--drivers/net/macb.c8
-rw-r--r--drivers/net/mdio_mux_i2creg.c108
-rw-r--r--drivers/net/mdio_sandbox.c4
-rw-r--r--drivers/net/mvmdio.c236
-rw-r--r--drivers/net/mvpp2.c8
-rw-r--r--drivers/net/pfe_eth/pfe_mdio.c3
-rw-r--r--include/env_callback.h2
-rw-r--r--include/env_flags.h2
-rw-r--r--include/net.h2
-rw-r--r--include/net/pcap.h55
-rw-r--r--include/netdev.h3
-rw-r--r--net/Makefile1
-rw-r--r--net/eth-uclass.c5
-rw-r--r--net/eth_legacy.c10
-rw-r--r--net/mdio-uclass.c13
-rw-r--r--net/net.c14
-rw-r--r--net/nfs.c19
-rw-r--r--net/nfs.h2
-rw-r--r--net/pcap.c156
39 files changed, 911 insertions, 57 deletions
diff --git a/Makefile b/Makefile
index c02accfc26..ae56e47b2c 100644
--- a/Makefile
+++ b/Makefile
@@ -1026,6 +1026,17 @@ ifneq ($(CONFIG_WDT),y)
@echo >&2 "===================================================="
endif
endif
+ifneq ($(CONFIG_NET),)
+ifneq ($(CONFIG_DM_ETH),y)
+ @echo >&2 "===================== WARNING ======================"
+ @echo >&2 "This board does not use CONFIG_DM_ETH (Driver Model"
+ @echo >&2 "for Ethernet drivers). Please update the board to use"
+ @echo >&2 "CONFIG_DM_ETH before the v2020.07 release. Failure to"
+ @echo >&2 "update by the deadline may result in board removal."
+ @echo >&2 "See doc/driver-model/migration.rst for more info."
+ @echo >&2 "===================================================="
+endif
+endif
@# Check that this build does not use CONFIG options that we do not
@# know about unless they are in Kconfig. All the existing CONFIG
@# options are whitelisted, so new ones should not be added.
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/Kconfig b/arch/arm/cpu/armv8/fsl-layerscape/Kconfig
index 42d31fdab0..54d03ae622 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/Kconfig
+++ b/arch/arm/cpu/armv8/fsl-layerscape/Kconfig
@@ -245,14 +245,6 @@ config FSL_LSCH3
config NXP_LSCH3_2
bool
-config FSL_MC_ENET
- bool "Management Complex network"
- depends on ARCH_LS2080A || ARCH_LS1088A || ARCH_LX2160A
- default y
- select RESV_RAM
- help
- Enable Management Complex (MC) network
-
menu "Layerscape architecture"
depends on FSL_LSCH2 || FSL_LSCH3
@@ -593,15 +585,6 @@ config SYS_FSL_HAS_RGMII
bool
depends on SYS_FSL_EC1 || SYS_FSL_EC2
-
-config SYS_MC_RSV_MEM_ALIGN
- hex "Management Complex reserved memory alignment"
- depends on RESV_RAM
- default 0x20000000 if ARCH_LS2080A || ARCH_LS1088A || ARCH_LX2160A
- help
- Reserved memory needs to be aligned for MC to use. Default value
- is 512MB.
-
config SPL_LDSCRIPT
default "arch/arm/cpu/armv8/u-boot-spl.lds" if ARCH_LS1043A || ARCH_LS1046A || ARCH_LS2080A
diff --git a/arch/arm/dts/armada-cp110-master.dtsi b/arch/arm/dts/armada-cp110-master.dtsi
index 551d00d774..e4c17e9f4b 100644
--- a/arch/arm/dts/armada-cp110-master.dtsi
+++ b/arch/arm/dts/armada-cp110-master.dtsi
@@ -96,6 +96,7 @@
#size-cells = <0>;
compatible = "marvell,orion-mdio";
reg = <0x12a200 0x10>;
+ device-name = "cpm-mdio";
};
cpm_syscon0: system-controller@440000 {
diff --git a/arch/arm/dts/armada-cp110-slave.dtsi b/arch/arm/dts/armada-cp110-slave.dtsi
index 2ea9004f1d..2fbd7b5514 100644
--- a/arch/arm/dts/armada-cp110-slave.dtsi
+++ b/arch/arm/dts/armada-cp110-slave.dtsi
@@ -96,6 +96,7 @@
#size-cells = <0>;
compatible = "marvell,orion-mdio";
reg = <0x12a200 0x10>;
+ device-name = "cps-mdio";
};
cps_syscon0: system-controller@440000 {
diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c
index fc14ad375c..18f9b84876 100644
--- a/board/st/stm32mp1/stm32mp1.c
+++ b/board/st/stm32mp1/stm32mp1.c
@@ -17,6 +17,7 @@
#include <misc.h>
#include <mtd.h>
#include <mtd_node.h>
+#include <netdev.h>
#include <phy.h>
#include <remoteproc.h>
#include <reset.h>
@@ -683,12 +684,21 @@ void board_quiesce_devices(void)
#endif
}
-/* board interface eth init */
-int board_interface_eth_init(phy_interface_t interface_type,
- bool eth_clk_sel_reg, bool eth_ref_clk_sel_reg)
+/* eth init function : weak called in eqos driver */
+int board_interface_eth_init(struct udevice *dev,
+ phy_interface_t interface_type)
{
u8 *syscfg;
u32 value;
+ bool eth_clk_sel_reg = false;
+ bool eth_ref_clk_sel_reg = false;
+
+ /* Gigabit Ethernet 125MHz clock selection. */
+ eth_clk_sel_reg = dev_read_bool(dev, "st,eth_clk_sel");
+
+ /* Ethernet 50Mhz RMII clock selection */
+ eth_ref_clk_sel_reg =
+ dev_read_bool(dev, "st,eth_ref_clk_sel");
syscfg = (u8 *)syscon_get_first_range(STM32MP_SYSCON_SYSCFG);
diff --git a/cmd/Kconfig b/cmd/Kconfig
index 05872fa0d7..98647f58b7 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -1339,6 +1339,13 @@ config BOOTP_NTPSERVER
bool "Request & store 'ntpserverip' from BOOTP/DHCP server"
depends on CMD_BOOTP
+config CMD_PCAP
+ bool "pcap capture"
+ help
+ Selecting this will allow capturing all Ethernet packets and store
+ them in physical memory in a PCAP formated file,
+ later to be analyzed by PCAP reader application (IE. WireShark).
+
config BOOTP_PXE
bool "Send PXE client arch to BOOTP/DHCP server"
default y
diff --git a/cmd/Makefile b/cmd/Makefile
index 58827b5679..ac843b4b16 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -103,6 +103,7 @@ obj-$(CONFIG_CMD_NVEDIT_EFI) += nvedit_efi.o
obj-$(CONFIG_CMD_ONENAND) += onenand.o
obj-$(CONFIG_CMD_OSD) += osd.o
obj-$(CONFIG_CMD_PART) += part.o
+obj-$(CONFIG_CMD_PCAP) += pcap.o
ifdef CONFIG_PCI
obj-$(CONFIG_CMD_PCI) += pci.o
endif
diff --git a/cmd/mdio.c b/cmd/mdio.c
index add6440813..22c8fbe856 100644
--- a/cmd/mdio.c
+++ b/cmd/mdio.c
@@ -253,12 +253,13 @@ static int do_mdio(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
case 'w':
if (pos > 1)
data = simple_strtoul(argv[pos--], NULL, 16);
+ /* Intentional fall-through - Get reg for read and write */
case 'r':
if (pos > 1)
if (extract_reg_range(argv[pos--], &devadlo, &devadhi,
&reglo, &reghi))
return CMD_RET_FAILURE;
-
+ /* Intentional fall-through - Get phy for all commands */
default:
if (pos > 1)
if (extract_phy_range(&argv[2], pos - 1, &bus,
diff --git a/cmd/pcap.c b/cmd/pcap.c
new file mode 100644
index 0000000000..980603f7bd
--- /dev/null
+++ b/cmd/pcap.c
@@ -0,0 +1,71 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2019
+ * Ramon Fried <rfried.dev@gmail.com>
+ */
+
+#include <common.h>
+#include <command.h>
+#include <net.h>
+#include <net/pcap.h>
+
+static int do_pcap_init(cmd_tbl_t *cmdtp, int flag, int argc,
+ char * const argv[])
+{
+ phys_addr_t addr;
+ unsigned int size;
+
+ if (argc != 3)
+ return CMD_RET_USAGE;
+
+ addr = simple_strtoul(argv[1], NULL, 16);
+ size = simple_strtoul(argv[2], NULL, 10);
+
+ return pcap_init(addr, size) ? CMD_RET_FAILURE : CMD_RET_SUCCESS;
+}
+
+static int do_pcap_start(cmd_tbl_t *cmdtp, int flag, int argc,
+ char * const argv[])
+{
+ return pcap_start_stop(true) ? CMD_RET_FAILURE : CMD_RET_SUCCESS;
+}
+
+static int do_pcap_stop(cmd_tbl_t *cmdtp, int flag, int argc,
+ char * const argv[])
+{
+ return pcap_start_stop(false) ? CMD_RET_FAILURE : CMD_RET_SUCCESS;
+}
+
+static int do_pcap_status(cmd_tbl_t *cmdtp, int flag, int argc,
+ char * const argv[])
+{
+ return pcap_print_status() ? CMD_RET_FAILURE : CMD_RET_SUCCESS;
+}
+
+static int do_pcap_clear(cmd_tbl_t *cmdtp, int flag, int argc,
+ char * const argv[])
+{
+ return pcap_clear() ? CMD_RET_FAILURE : CMD_RET_SUCCESS;
+}
+
+static char pcap_help_text[] =
+ "- network packet capture\n\n"
+ "pcap\n"
+ "pcap init\t\t\t<addr> <max_size>\n"
+ "pcap start\t\t\tstart capture\n"
+ "pcap stop\t\t\tstop capture\n"
+ "pcap status\t\t\tprint status\n"
+ "pcap clear\t\t\tclear capture buffer\n"
+ "\n"
+ "With:\n"
+ "\t<addr>: user address to which pcap will be stored (hexedcimal)\n"
+ "\t<max_size>: Maximum size of pcap file (decimal)\n"
+ "\n";
+
+U_BOOT_CMD_WITH_SUBCMDS(pcap, "pcap", pcap_help_text,
+ U_BOOT_SUBCMD_MKENT(init, 3, 0, do_pcap_init),
+ U_BOOT_SUBCMD_MKENT(start, 1, 0, do_pcap_start),
+ U_BOOT_SUBCMD_MKENT(stop, 1, 0, do_pcap_stop),
+ U_BOOT_SUBCMD_MKENT(status, 1, 0, do_pcap_status),
+ U_BOOT_SUBCMD_MKENT(clear, 1, 0, do_pcap_clear),
+);
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 7355e3aa1e..968ffdab61 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -49,6 +49,7 @@ CONFIG_CMD_SPI=y
CONFIG_CMD_USB=y
CONFIG_CMD_AXI=y
CONFIG_CMD_AB_SELECT=y
+CONFIG_CMD_PCAP=y
CONFIG_CMD_TFTPPUT=y
CONFIG_CMD_TFTPSRV=y
CONFIG_CMD_RARP=y
diff --git a/doc/README.pcap b/doc/README.pcap
new file mode 100644
index 0000000000..97b3e55fd8
--- /dev/null
+++ b/doc/README.pcap
@@ -0,0 +1,62 @@
+PCAP:
+
+U-boot supports live Ethernet packet capture in PCAP(2.4) format.
+This is enabled by CONFIG_CMD_PCAP.
+
+The capture is stored on physical memory, and should be copied to
+a machine capable of parsing and displaying PCAP files (IE. wireshark)
+If networking works properly one can copy the capture file from physical memory
+using tftpput, or save it to local storage with (sf write, mmc write, fatwrite, etc)
+
+the pcap capturing requires maximum buffer size.
+when the buffer is full an error message will be displayed and then packets
+will silently drop.
+the actual capture file size is populate in the environment variable "pcapsize".
+
+Usage example:
+
+# Initialize pcap capture to physical address (0x100000) with maximum size of
+# 100000 bytes.
+
+# Start capture
+pcap start
+
+# Initialize network activity
+env set ipaddr 10.0.2.15; env set serverip 10.0.2.2; tftp uImage64
+
+# Stop capture
+pcap stop
+
+# pcap init 0x100000 100000
+PCAP capture initialized: addr: 0xffffffff80100000 max length: 100000
+
+# pcap start
+# env set ipaddr 10.0.2.15; env set serverip 10.0.2.2; tftp uImage64
+eth0@10000000: PHY present at 0
+eth0@10000000: link up, 1000Mbps full-duplex (lpa: 0x7c00)
+Using eth0@10000000 device
+TFTP from server 10.0.2.2; our IP address is 10.0.2.15
+Filename 'uImage64'.
+Load address: 0xffffffff88000000
+Loading: #################################################################
+ #################################################################
+ #################################################################
+ #################################################################
+!!! Buffer is full, consider increasing buffer size !!!
+ #################################################################
+ #################################################################
+ #################################################################
+ #################################################################
+ #################################################################
+ #
+ 18.2 MiB/s
+done
+Bytes transferred = 8359376 (7f8dd0 hex)
+PCAP status:
+ Initialized addr: 0xffffffff80100000 max length: 100000
+ Status: Active. file size: 99991
+ Incoming packets: 66 Outgoing packets: 67
+
+# pcap stop
+# tftpput 0xffffffff80100000 $pcapsize 10.0.2.2:capture.pcap
+
diff --git a/doc/device-tree-bindings/net/marvell-mdio.txt b/doc/device-tree-bindings/net/marvell-mdio.txt
new file mode 100644
index 0000000000..e2038e2145
--- /dev/null
+++ b/doc/device-tree-bindings/net/marvell-mdio.txt
@@ -0,0 +1,15 @@
+* Marvell MDIO Ethernet Controller interface
+
+The Ethernet controllers of the Marvel Armada 3700 and Armada 7k/8k
+have an identical unit that provides an interface with the MDIO bus.
+This driver handles this MDIO interface.
+
+Mandatory properties:
+SoC specific:
+ - #address-cells: Must be <1>.
+ - #size-cells: Must be <0>.
+ - compatible: Should be "marvell,orion-mdio" (for SMI)
+ "marvell,xmdio" (for XSMI)
+ - reg: Base address and size SMI/XMSI bus.
+
+Please refer to "mdio.txt" for generic MDIO bus bindings.
diff --git a/doc/device-tree-bindings/net/mdio.txt b/doc/device-tree-bindings/net/mdio.txt
new file mode 100644
index 0000000000..1595325050
--- /dev/null
+++ b/doc/device-tree-bindings/net/mdio.txt
@@ -0,0 +1,36 @@
+Common MDIO bus properties.
+
+These are generic properties that can apply to any MDIO bus.
+
+Optional properties:
+ - device-name - If present it is used to name the device and MDIO bus.
+ The name must be unique and must not contain spaces.
+
+A list of child nodes, one per device on the bus is expected. These could be
+PHYs, switches or similar devices and child nodes should follow the specific
+binding for the device type.
+
+Example :
+This example shows the structure used for the external MDIO bus on NXP LS1028A
+RDB board. Note that this MDIO device is an integrated PCI function and
+requires no compatible property for probing.
+
+/* definition in SoC dtsi file */
+ pcie@1f0000000 {
+
+ mdio0: pci@0,3 {
+ #address-cells=<0>;
+ #size-cells=<1>;
+ reg = <0x000300 0 0 0 0>;
+ status = "disabled";
+ device-name = "emdio";
+ };
+ };
+/* definition of PHYs in RDB dts file */
+&mdio0 {
+ status = "okay";
+ rdb_phy0: phy@2 {
+ reg = <2>;
+ };
+};
+
diff --git a/doc/driver-model/migration.rst b/doc/driver-model/migration.rst
index a26e7ab7e1..75b85235ef 100644
--- a/doc/driver-model/migration.rst
+++ b/doc/driver-model/migration.rst
@@ -97,3 +97,11 @@ Deadline: 2019.07
The video subsystem has supported driver model since early 2016. Maintainers
should submit patches switching over to using CONFIG_DM_VIDEO and other base
driver model options in time for inclusion in the 2019.07 release.
+
+CONFIG_DM_ETH
+-------------
+Deadline: 2020.07
+
+The network subsystem has supported the driver model since early 2015.
+Maintainers should submit patches switching over to using CONFIG_DM_ETH and
+other base driver model options in time for inclusion in the 2020.07 release.
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 084e095229..2ce3092db0 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -1,5 +1,6 @@
source "drivers/net/phy/Kconfig"
source "drivers/net/pfe_eth/Kconfig"
+source "drivers/net/fsl-mc/Kconfig"
config DM_ETH
bool "Enable Driver Model for Ethernet drivers"
@@ -603,4 +604,14 @@ config MDIO_MUX_I2CREG
an I2C chip. The board it was developed for uses a mux controlled by
on-board FPGA which in turn is accessed as a chip over I2C.
+config MVMDIO
+ bool "Marvell MDIO interface support"
+ depends on DM_MDIO
+ help
+ This driver supports the MDIO interface found in the network
+ interface units of the Marvell EBU SoCs (Kirkwood, Orion5x,
+ Dove, Armada 370, Armada XP, Armada 37xx and Armada7K/8K/8KP).
+
+ This driver is used by the MVPP2 and MVNETA drivers.
+
endif # NETDEVICES
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 71c0889355..30991834ec 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -42,6 +42,7 @@ obj-$(CONFIG_MDIO_MUX_SANDBOX) += mdio_mux_sandbox.o
obj-$(CONFIG_MPC8XX_FEC) += mpc8xx_fec.o
obj-$(CONFIG_MT7628_ETH) += mt7628-eth.o
obj-$(CONFIG_MVGBE) += mvgbe.o
+obj-$(CONFIG_MVMDIO) += mvmdio.o
obj-$(CONFIG_MVNETA) += mvneta.o
obj-$(CONFIG_MVPP2) += mvpp2.o
obj-$(CONFIG_NATSEMI) += natsemi.o
diff --git a/drivers/net/designware.c b/drivers/net/designware.c
index c4fe40b19a..145eeac45f 100644
--- a/drivers/net/designware.c
+++ b/drivers/net/designware.c
@@ -847,7 +847,6 @@ int designware_eth_ofdata_to_platdata(struct udevice *dev)
static const struct udevice_id designware_eth_ids[] = {
{ .compatible = "allwinner,sun7i-a20-gmac" },
- { .compatible = "altr,socfpga-stmmac" },
{ .compatible = "amlogic,meson6-dwmac" },
{ .compatible = "amlogic,meson-gx-dwmac" },
{ .compatible = "amlogic,meson-gxbb-dwmac" },
diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c
index 07b36675a7..455709338c 100644
--- a/drivers/net/dwc_eth_qos.c
+++ b/drivers/net/dwc_eth_qos.c
@@ -621,7 +621,7 @@ err:
return ret;
}
-void eqos_stop_clks_tegra186(struct udevice *dev)
+static void eqos_stop_clks_tegra186(struct udevice *dev)
{
struct eqos_priv *eqos = dev_get_priv(dev);
@@ -636,7 +636,7 @@ void eqos_stop_clks_tegra186(struct udevice *dev)
debug("%s: OK\n", __func__);
}
-void eqos_stop_clks_stm32(struct udevice *dev)
+static void eqos_stop_clks_stm32(struct udevice *dev)
{
struct eqos_priv *eqos = dev_get_priv(dev);
@@ -1290,7 +1290,7 @@ err:
return ret;
}
-void eqos_stop(struct udevice *dev)
+static void eqos_stop(struct udevice *dev)
{
struct eqos_priv *eqos = dev_get_priv(dev);
int i;
@@ -1344,7 +1344,7 @@ void eqos_stop(struct udevice *dev)
debug("%s: OK\n", __func__);
}
-int eqos_send(struct udevice *dev, void *packet, int length)
+static int eqos_send(struct udevice *dev, void *packet, int length)
{
struct eqos_priv *eqos = dev_get_priv(dev);
struct eqos_desc *tx_desc;
@@ -1385,7 +1385,7 @@ int eqos_send(struct udevice *dev, void *packet, int length)
return -ETIMEDOUT;
}
-int eqos_recv(struct udevice *dev, int flags, uchar **packetp)
+static int eqos_recv(struct udevice *dev, int flags, uchar **packetp)
{
struct eqos_priv *eqos = dev_get_priv(dev);
struct eqos_desc *rx_desc;
@@ -1409,7 +1409,7 @@ int eqos_recv(struct udevice *dev, int flags, uchar **packetp)
return length;
}
-int eqos_free_pkt(struct udevice *dev, uchar *packet, int length)
+static int eqos_free_pkt(struct udevice *dev, uchar *packet, int length)
{
struct eqos_priv *eqos = dev_get_priv(dev);
uchar *packet_expected;
@@ -1591,8 +1591,8 @@ err_free_reset_eqos:
}
/* board-specific Ethernet Interface initializations. */
-__weak int board_interface_eth_init(int interface_type, bool eth_clk_sel_reg,
- bool eth_ref_clk_sel_reg)
+__weak int board_interface_eth_init(struct udevice *dev,
+ phy_interface_t interface_type)
{
return 0;
}
@@ -1602,8 +1602,6 @@ static int eqos_probe_resources_stm32(struct udevice *dev)
struct eqos_priv *eqos = dev_get_priv(dev);
int ret;
phy_interface_t interface;
- bool eth_clk_sel_reg = false;
- bool eth_ref_clk_sel_reg = false;
debug("%s(dev=%p):\n", __func__, dev);
@@ -1614,15 +1612,7 @@ static int eqos_probe_resources_stm32(struct udevice *dev)
return -EINVAL;
}
- /* Gigabit Ethernet 125MHz clock selection. */
- eth_clk_sel_reg = dev_read_bool(dev, "st,eth_clk_sel");
-
- /* Ethernet 50Mhz RMII clock selection */
- eth_ref_clk_sel_reg =
- dev_read_bool(dev, "st,eth_ref_clk_sel");
-
- ret = board_interface_eth_init(interface, eth_clk_sel_reg,
- eth_ref_clk_sel_reg);
+ ret = board_interface_eth_init(dev, interface);
if (ret)
return -EINVAL;
diff --git a/drivers/net/fsl-mc/Kconfig b/drivers/net/fsl-mc/Kconfig
new file mode 100644
index 0000000000..25a2cb8ffa
--- /dev/null
+++ b/drivers/net/fsl-mc/Kconfig
@@ -0,0 +1,25 @@
+#
+# NXP Management Complex
+#
+
+menuconfig FSL_MC_ENET
+ bool "NXP Management Complex"
+ depends on ARCH_LS2080A || ARCH_LS1088A || ARCH_LX2160A
+ default y
+ select RESV_RAM
+ help
+ Enable Management Complex (MC) network
+ This is NXP Management Complex menuconfig
+ that contains all MC related config options
+
+if FSL_MC_ENET
+
+config SYS_MC_RSV_MEM_ALIGN
+ hex "Management Complex reserved memory alignment"
+ depends on RESV_RAM
+ default 0x20000000 if ARCH_LS2080A || ARCH_LS1088A || ARCH_LX2160A
+ help
+ Reserved memory needs to be aligned for MC to use. Default value
+ is 512MB.
+
+endif # FSL_MC_ENET
diff --git a/drivers/net/fsl_enetc_mdio.c b/drivers/net/fsl_enetc_mdio.c
index 60d21537b8..b4463a58a5 100644
--- a/drivers/net/fsl_enetc_mdio.c
+++ b/drivers/net/fsl_enetc_mdio.c
@@ -144,6 +144,7 @@ U_BOOT_DRIVER(enetc_mdio) = {
static struct pci_device_id enetc_mdio_ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, PCI_DEVICE_ID_ENETC_MDIO) },
+ { }
};
U_BOOT_PCI_DEVICE(enetc_mdio, enetc_mdio_ids);
diff --git a/drivers/net/macb.c b/drivers/net/macb.c
index c99cf663a4..377188e361 100644
--- a/drivers/net/macb.c
+++ b/drivers/net/macb.c
@@ -296,13 +296,15 @@ static inline void macb_flush_ring_desc(struct macb_device *macb, bool rx)
static inline void macb_flush_rx_buffer(struct macb_device *macb)
{
flush_dcache_range(macb->rx_buffer_dma, macb->rx_buffer_dma +
- ALIGN(MACB_RX_BUFFER_SIZE, PKTALIGN));
+ ALIGN(macb->rx_buffer_size * MACB_RX_RING_SIZE,
+ PKTALIGN));
}
static inline void macb_invalidate_rx_buffer(struct macb_device *macb)
{
invalidate_dcache_range(macb->rx_buffer_dma, macb->rx_buffer_dma +
- ALIGN(MACB_RX_BUFFER_SIZE, PKTALIGN));
+ ALIGN(macb->rx_buffer_size * MACB_RX_RING_SIZE,
+ PKTALIGN));
}
#if defined(CONFIG_CMD_NET)
@@ -643,7 +645,7 @@ static int macb_phy_init(struct macb_device *macb, const char *name)
/* First check for GMAC and that it is GiB capable */
if (gem_is_gigabit_capable(macb)) {
- lpa = macb_mdio_read(macb, MII_LPA);
+ lpa = macb_mdio_read(macb, MII_STAT1000);
if (lpa & (LPA_1000FULL | LPA_1000HALF | LPA_1000XFULL |
LPA_1000XHALF)) {
diff --git a/drivers/net/mdio_mux_i2creg.c b/drivers/net/mdio_mux_i2creg.c
new file mode 100644
index 0000000000..3e82898f46
--- /dev/null
+++ b/drivers/net/mdio_mux_i2creg.c
@@ -0,0 +1,108 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2019
+ * Alex Marginean, NXP
+ */
+
+#include <dm.h>
+#include <errno.h>
+#include <miiphy.h>
+#include <i2c.h>
+
+/*
+ * This driver is used for MDIO muxes driven by writing to a register of an I2C
+ * chip. The board it was developed for uses a mux controlled by on-board FPGA
+ * which in turn is accessed as a chip over I2C.
+ */
+
+struct mdio_mux_i2creg_priv {
+ struct udevice *chip;
+ int reg;
+ int mask;
+};
+
+static int mdio_mux_i2creg_select(struct udevice *mux, int cur, int sel)
+{
+ struct mdio_mux_i2creg_priv *priv = dev_get_priv(mux);
+ u8 val, val_old;
+
+ /* if last selection didn't change we're good to go */
+ if (cur == sel)
+ return 0;
+
+ val_old = dm_i2c_reg_read(priv->chip, priv->reg);
+ val = (val_old & ~priv->mask) | (sel & priv->mask);
+ debug("%s: chip %s, reg %x, val %x => %x\n", __func__, priv->chip->name,
+ priv->reg, val_old, val);
+ dm_i2c_reg_write(priv->chip, priv->reg, val);
+
+ return 0;
+}
+
+static const struct mdio_mux_ops mdio_mux_i2creg_ops = {
+ .select = mdio_mux_i2creg_select,
+};
+
+static int mdio_mux_i2creg_probe(struct udevice *dev)
+{
+ struct mdio_mux_i2creg_priv *priv = dev_get_priv(dev);
+ ofnode chip_node, bus_node;
+ struct udevice *i2c_bus;
+ u32 reg_mask[2];
+ u32 chip_addr;
+ int err;
+
+ /* read the register addr/mask pair */
+ err = dev_read_u32_array(dev, "mux-reg-masks", reg_mask, 2);
+ if (err) {
+ debug("%s: error reading mux-reg-masks property\n", __func__);
+ return err;
+ }
+
+ /* parent should be an I2C chip, grandparent should be an I2C bus */
+ chip_node = ofnode_get_parent(dev->node);
+ bus_node = ofnode_get_parent(chip_node);
+
+ err = uclass_get_device_by_ofnode(UCLASS_I2C, bus_node, &i2c_bus);
+ if (err) {
+ debug("%s: can't find I2C bus for node %s\n", __func__,
+ ofnode_get_name(bus_node));
+ return err;
+ }
+
+ err = ofnode_read_u32(chip_node, "reg", &chip_addr);
+ if (err) {
+ debug("%s: can't read chip address in %s\n", __func__,
+ ofnode_get_name(chip_node));
+ return err;
+ }
+
+ err = i2c_get_chip(i2c_bus, (uint)chip_addr, 1, &priv->chip);
+ if (err) {
+ debug("%s: can't find i2c chip device for addr %x\n", __func__,
+ chip_addr);
+ return err;
+ }
+
+ priv->reg = (int)reg_mask[0];
+ priv->mask = (int)reg_mask[1];
+
+ debug("%s: chip %s, reg %x, mask %x\n", __func__, priv->chip->name,
+ priv->reg, priv->mask);
+
+ return 0;
+}
+
+static const struct udevice_id mdio_mux_i2creg_ids[] = {
+ { .compatible = "mdio-mux-i2creg" },
+ { }
+};
+
+U_BOOT_DRIVER(mdio_mux_i2creg) = {
+ .name = "mdio_mux_i2creg",
+ .id = UCLASS_MDIO_MUX,
+ .of_match = mdio_mux_i2creg_ids,
+ .probe = mdio_mux_i2creg_probe,
+ .ops = &mdio_mux_i2creg_ops,
+ .priv_auto_alloc_size = sizeof(struct mdio_mux_i2creg_priv),
+};
diff --git a/drivers/net/mdio_sandbox.c b/drivers/net/mdio_sandbox.c
index df053f5381..b731f60a98 100644
--- a/drivers/net/mdio_sandbox.c
+++ b/drivers/net/mdio_sandbox.c
@@ -27,7 +27,7 @@ static int mdio_sandbox_read(struct udevice *dev, int addr, int devad, int reg)
return -ENODEV;
if (devad != MDIO_DEVAD_NONE)
return -ENODEV;
- if (reg < 0 || reg > SANDBOX_PHY_REG_CNT)
+ if (reg < 0 || reg >= SANDBOX_PHY_REG_CNT)
return -ENODEV;
return priv->reg[reg];
@@ -45,7 +45,7 @@ static int mdio_sandbox_write(struct udevice *dev, int addr, int devad, int reg,
return -ENODEV;
if (devad != MDIO_DEVAD_NONE)
return -ENODEV;
- if (reg < 0 || reg > SANDBOX_PHY_REG_CNT)
+ if (reg < 0 || reg >= SANDBOX_PHY_REG_CNT)
return -ENODEV;
priv->reg[reg] = val;
diff --git a/drivers/net/mvmdio.c b/drivers/net/mvmdio.c
new file mode 100644
index 0000000000..ec6805e536
--- /dev/null
+++ b/drivers/net/mvmdio.c
@@ -0,0 +1,236 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ * Author: Ken Ma<make@marvell.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
+#include <miiphy.h>
+#include <phy.h>
+#include <asm/io.h>
+#include <wait_bit.h>
+
+#define MVMDIO_SMI_DATA_SHIFT 0
+#define MVMDIO_SMI_PHY_ADDR_SHIFT 16
+#define MVMDIO_SMI_PHY_REG_SHIFT 21
+#define MVMDIO_SMI_READ_OPERATION BIT(26)
+#define MVMDIO_SMI_WRITE_OPERATION 0
+#define MVMDIO_SMI_READ_VALID BIT(27)
+#define MVMDIO_SMI_BUSY BIT(28)
+
+#define MVMDIO_XSMI_MGNT_REG 0x0
+#define MVMDIO_XSMI_PHYADDR_SHIFT 16
+#define MVMDIO_XSMI_DEVADDR_SHIFT 21
+#define MVMDIO_XSMI_WRITE_OPERATION (0x5 << 26)
+#define MVMDIO_XSMI_READ_OPERATION (0x7 << 26)
+#define MVMDIO_XSMI_READ_VALID BIT(29)
+#define MVMDIO_XSMI_BUSY BIT(30)
+#define MVMDIO_XSMI_ADDR_REG 0x8
+
+enum mvmdio_bus_type {
+ BUS_TYPE_SMI,
+ BUS_TYPE_XSMI
+};
+
+struct mvmdio_priv {
+ void *mdio_base;
+ enum mvmdio_bus_type type;
+};
+
+static int mvmdio_smi_read(struct udevice *dev, int addr,
+ int devad, int reg)
+{
+ struct mvmdio_priv *priv = dev_get_priv(dev);
+ u32 val;
+ int ret;
+
+ if (devad != MDIO_DEVAD_NONE)
+ return -EOPNOTSUPP;
+
+ ret = wait_for_bit_le32(priv->mdio_base, MVMDIO_SMI_BUSY,
+ false, CONFIG_SYS_HZ, false);
+ if (ret < 0)
+ return ret;
+
+ writel(((addr << MVMDIO_SMI_PHY_ADDR_SHIFT) |
+ (reg << MVMDIO_SMI_PHY_REG_SHIFT) |
+ MVMDIO_SMI_READ_OPERATION),
+ priv->mdio_base);
+
+ ret = wait_for_bit_le32(priv->mdio_base, MVMDIO_SMI_BUSY,
+ false, CONFIG_SYS_HZ, false);
+ if (ret < 0)
+ return ret;
+
+ val = readl(priv->mdio_base);
+ if (!(val & MVMDIO_SMI_READ_VALID)) {
+ pr_err("SMI bus read not valid\n");
+ return -ENODEV;
+ }
+
+ return val & GENMASK(15, 0);
+}
+
+static int mvmdio_smi_write(struct udevice *dev, int addr, int devad,
+ int reg, u16 value)
+{
+ struct mvmdio_priv *priv = dev_get_priv(dev);
+ int ret;
+
+ if (devad != MDIO_DEVAD_NONE)
+ return -EOPNOTSUPP;
+
+ ret = wait_for_bit_le32(priv->mdio_base, MVMDIO_SMI_BUSY,
+ false, CONFIG_SYS_HZ, false);
+ if (ret < 0)
+ return ret;
+
+ writel(((addr << MVMDIO_SMI_PHY_ADDR_SHIFT) |
+ (reg << MVMDIO_SMI_PHY_REG_SHIFT) |
+ MVMDIO_SMI_WRITE_OPERATION |
+ (value << MVMDIO_SMI_DATA_SHIFT)),
+ priv->mdio_base);
+
+ return 0;
+}
+
+static int mvmdio_xsmi_read(struct udevice *dev, int addr,
+ int devad, int reg)
+{
+ struct mvmdio_priv *priv = dev_get_priv(dev);
+ int ret;
+
+ if (devad == MDIO_DEVAD_NONE)
+ return -EOPNOTSUPP;
+
+ ret = wait_for_bit_le32(priv->mdio_base, MVMDIO_XSMI_BUSY,
+ false, CONFIG_SYS_HZ, false);
+ if (ret < 0)
+ return ret;
+
+ writel(reg & GENMASK(15, 0), priv->mdio_base + MVMDIO_XSMI_ADDR_REG);
+ writel(((addr << MVMDIO_XSMI_PHYADDR_SHIFT) |
+ (devad << MVMDIO_XSMI_DEVADDR_SHIFT) |
+ MVMDIO_XSMI_READ_OPERATION),
+ priv->mdio_base + MVMDIO_XSMI_MGNT_REG);
+
+ ret = wait_for_bit_le32(priv->mdio_base, MVMDIO_XSMI_BUSY,
+ false, CONFIG_SYS_HZ, false);
+ if (ret < 0)
+ return ret;
+
+ if (!(readl(priv->mdio_base + MVMDIO_XSMI_MGNT_REG) &
+ MVMDIO_XSMI_READ_VALID)) {
+ pr_err("XSMI bus read not valid\n");
+ return -ENODEV;
+ }
+
+ return readl(priv->mdio_base + MVMDIO_XSMI_MGNT_REG) & GENMASK(15, 0);
+}
+
+static int mvmdio_xsmi_write(struct udevice *dev, int addr, int devad,
+ int reg, u16 value)
+{
+ struct mvmdio_priv *priv = dev_get_priv(dev);
+ int ret;
+
+ if (devad == MDIO_DEVAD_NONE)
+ return -EOPNOTSUPP;
+
+ ret = wait_for_bit_le32(priv->mdio_base, MVMDIO_XSMI_BUSY,
+ false, CONFIG_SYS_HZ, false);
+ if (ret < 0)
+ return ret;
+
+ writel(reg & GENMASK(15, 0), priv->mdio_base + MVMDIO_XSMI_ADDR_REG);
+ writel(((addr << MVMDIO_XSMI_PHYADDR_SHIFT) |
+ (devad << MVMDIO_XSMI_DEVADDR_SHIFT) |
+ MVMDIO_XSMI_WRITE_OPERATION | value),
+ priv->mdio_base + MVMDIO_XSMI_MGNT_REG);
+
+ return 0;
+}
+
+static int mvmdio_read(struct udevice *dev, int addr, int devad, int reg)
+{
+ struct mvmdio_priv *priv = dev_get_priv(dev);
+ int err = -ENOTSUPP;
+
+ switch (priv->type) {
+ case BUS_TYPE_SMI:
+ err = mvmdio_smi_read(dev, addr, devad, reg);
+ break;
+ case BUS_TYPE_XSMI:
+ err = mvmdio_xsmi_read(dev, addr, devad, reg);
+ break;
+ }
+
+ return err;
+}
+
+static int mvmdio_write(struct udevice *dev, int addr, int devad, int reg,
+ u16 value)
+{
+ struct mvmdio_priv *priv = dev_get_priv(dev);
+ int err = -ENOTSUPP;
+
+ switch (priv->type) {
+ case BUS_TYPE_SMI:
+ err = mvmdio_smi_write(dev, addr, devad, reg, value);
+ break;
+ case BUS_TYPE_XSMI:
+ err = mvmdio_xsmi_write(dev, addr, devad, reg, value);
+ break;
+ }
+
+ return err;
+}
+
+/*
+ * Name the device, we use the device tree node name.
+ * This can be overwritten by MDIO class code if device-name property is
+ * present.
+ */
+static int mvmdio_bind(struct udevice *dev)
+{
+ if (ofnode_valid(dev->node))
+ device_set_name(dev, ofnode_get_name(dev->node));
+
+ return 0;
+}
+
+/* Get device base address and type, either C22 SMII or C45 XSMI */
+static int mvmdio_probe(struct udevice *dev)
+{
+ struct mvmdio_priv *priv = dev_get_priv(dev);
+
+ priv->mdio_base = (void *)dev_read_addr(dev);
+ priv->type = (enum mvmdio_bus_type)dev_get_driver_data(dev);
+
+ return 0;
+}
+
+static const struct mdio_ops mvmdio_ops = {
+ .read = mvmdio_read,
+ .write = mvmdio_write,
+};
+
+static const struct udevice_id mvmdio_ids[] = {
+ { .compatible = "marvell,orion-mdio", .data = BUS_TYPE_SMI },
+ { .compatible = "marvell,xmdio", .data = BUS_TYPE_XSMI },
+ { }
+};
+
+U_BOOT_DRIVER(mvmdio) = {
+ .name = "mvmdio",
+ .id = UCLASS_MDIO,
+ .of_match = mvmdio_ids,
+ .bind = mvmdio_bind,
+ .probe = mvmdio_probe,
+ .ops = &mvmdio_ops,
+ .priv_auto_alloc_size = sizeof(struct mvmdio_priv),
+};
+
diff --git a/drivers/net/mvpp2.c b/drivers/net/mvpp2.c
index bcc6fe92a9..bd89725e77 100644
--- a/drivers/net/mvpp2.c
+++ b/drivers/net/mvpp2.c
@@ -5321,6 +5321,13 @@ static void mvpp2_stop(struct udevice *dev)
mvpp2_cleanup_txqs(port);
}
+static int mvpp2_write_hwaddr(struct udevice *dev)
+{
+ struct mvpp2_port *port = dev_get_priv(dev);
+
+ return mvpp2_prs_update_mac_da(port, port->dev_addr);
+}
+
static int mvpp22_smi_phy_addr_cfg(struct mvpp2_port *port)
{
writel(port->phyaddr, port->priv->iface_base +
@@ -5525,6 +5532,7 @@ static const struct eth_ops mvpp2_ops = {
.send = mvpp2_send,
.recv = mvpp2_recv,
.stop = mvpp2_stop,
+ .write_hwaddr = mvpp2_write_hwaddr
};
static struct driver mvpp2_driver = {
diff --git a/drivers/net/pfe_eth/pfe_mdio.c b/drivers/net/pfe_eth/pfe_mdio.c
index 2dde9e7ac8..62309670fa 100644
--- a/drivers/net/pfe_eth/pfe_mdio.c
+++ b/drivers/net/pfe_eth/pfe_mdio.c
@@ -110,7 +110,6 @@ static int pfe_phy_write(struct mii_dev *bus, int phy_addr, int dev_addr,
u32 phy;
u32 reg_data;
int timeout = MDIO_TIMEOUT;
- int val;
if (dev_addr == MDIO_DEVAD_NONE) {
reg = ((reg_addr & EMAC_MII_DATA_RA_MASK) <<
@@ -150,7 +149,7 @@ static int pfe_phy_write(struct mii_dev *bus, int phy_addr, int dev_addr,
debug("%s: phy: %02x reg:%02x val:%#x\n", __func__, phy_addr,
reg_addr, data);
- return val;
+ return 0;
}
static void pfe_configure_serdes(struct pfe_eth_dev *priv)
diff --git a/include/env_callback.h b/include/env_callback.h
index 982c07854d..74da20eec3 100644
--- a/include/env_callback.h
+++ b/include/env_callback.h
@@ -42,7 +42,7 @@
#define DNS_CALLBACK
#endif
-#ifdef CONFIG_CMD_NET
+#ifdef CONFIG_NET
#define NET_CALLBACKS \
"bootfile:bootfile," \
"ipaddr:ipaddr," \
diff --git a/include/env_flags.h b/include/env_flags.h
index e5380f2948..725841a891 100644
--- a/include/env_flags.h
+++ b/include/env_flags.h
@@ -36,7 +36,7 @@ enum env_flags_varaccess {
#define CONFIG_ENV_FLAGS_LIST_STATIC ""
#endif
-#ifdef CONFIG_CMD_NET
+#ifdef CONFIG_NET
#ifdef CONFIG_REGEX
#define ETHADDR_WILDCARD "\\d*"
#else
diff --git a/include/net.h b/include/net.h
index a54d5eeac5..75a16e4c8f 100644
--- a/include/net.h
+++ b/include/net.h
@@ -816,7 +816,7 @@ static inline int is_valid_ethaddr(const u8 *addr)
static inline void net_random_ethaddr(uchar *addr)
{
int i;
- unsigned int seed = get_timer(0);
+ unsigned int seed = get_ticks();
for (i = 0; i < 6; i++)
addr[i] = rand_r(&seed);
diff --git a/include/net/pcap.h b/include/net/pcap.h
new file mode 100644
index 0000000000..512ba982f1
--- /dev/null
+++ b/include/net/pcap.h
@@ -0,0 +1,55 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright 2019
+ * Ramon Fried <rfried.dev@gmail.com>
+ */
+
+/**
+ * pcap_init() - Initialize PCAP memory buffer
+ *
+ * @paddr physicaly memory address to store buffer
+ * @size maximum size of capture file in memory
+ *
+ * @return 0 on success, -ERROR on error
+ */
+int pcap_init(phys_addr_t paddr, unsigned long size);
+
+/**
+ * pcap_start_stop() - start / stop pcap capture
+ *
+ * @start if true, start capture if false stop capture
+ *
+ * @return 0 on success, -ERROR on error
+ */
+int pcap_start_stop(bool start);
+
+/**
+ * pcap_clear() - clear pcap capture buffer and statistics
+ *
+ * @return 0 on success, -ERROR on error
+ */
+int pcap_clear(void);
+
+/**
+ * pcap_print_status() - print status of pcap capture
+ *
+ * @return 0 on success, -ERROR on error
+ */
+int pcap_print_status(void);
+
+/**
+ * pcap_active() - check if pcap is enabled
+ *
+ * @return TRUE if active, FALSE if not.
+ */
+bool pcap_active(void);
+
+/**
+ * pcap_post() - Post a packet to PCAP file
+ *
+ * @packet: packet to post
+ * @len: packet length in bytes
+ * @outgoing packet direction (outgoing/incoming)
+ * @return 0 on success, -ERROR on error
+ */
+int pcap_post(const void *packet, size_t len, bool outgoing);
diff --git a/include/netdev.h b/include/netdev.h
index a40c4adaad..68a3fceab6 100644
--- a/include/netdev.h
+++ b/include/netdev.h
@@ -10,6 +10,7 @@
#ifndef _NETDEV_H_
#define _NETDEV_H_
+#include <phy_interface.h>
/*
* Board and CPU-specific initialization functions
@@ -21,6 +22,8 @@
*/
int board_eth_init(bd_t *bis);
+int board_interface_eth_init(struct udevice *dev,
+ phy_interface_t interface_type);
int cpu_eth_init(bd_t *bis);
/* Driver initialization prototypes */
diff --git a/net/Makefile b/net/Makefile
index 826544f05f..2a700c8401 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -22,6 +22,7 @@ obj-$(CONFIG_CMD_LINK_LOCAL) += link_local.o
obj-$(CONFIG_NET) += net.o
obj-$(CONFIG_CMD_NFS) += nfs.o
obj-$(CONFIG_CMD_PING) += ping.o
+obj-$(CONFIG_CMD_PCAP) += pcap.o
obj-$(CONFIG_CMD_RARP) += rarp.o
obj-$(CONFIG_CMD_SNTP) += sntp.o
obj-$(CONFIG_CMD_TFTPBOOT) += tftp.o
diff --git a/net/eth-uclass.c b/net/eth-uclass.c
index 1d5d2f03b7..3bd98b01ad 100644
--- a/net/eth-uclass.c
+++ b/net/eth-uclass.c
@@ -11,6 +11,7 @@
#include <net.h>
#include <dm/device-internal.h>
#include <dm/uclass-internal.h>
+#include <net/pcap.h>
#include "eth_internal.h"
DECLARE_GLOBAL_DATA_PTR;
@@ -344,6 +345,10 @@ int eth_send(void *packet, int length)
/* We cannot completely return the error at present */
debug("%s: send() returned error %d\n", __func__, ret);
}
+#if defined(CONFIG_CMD_PCAP)
+ if (ret >= 0)
+ pcap_post(packet, length, true);
+#endif
return ret;
}
diff --git a/net/eth_legacy.c b/net/eth_legacy.c
index 850f362d87..41f5263526 100644
--- a/net/eth_legacy.c
+++ b/net/eth_legacy.c
@@ -11,6 +11,7 @@
#include <net.h>
#include <phy.h>
#include <linux/errno.h>
+#include <net/pcap.h>
#include "eth_internal.h"
DECLARE_GLOBAL_DATA_PTR;
@@ -352,10 +353,17 @@ int eth_is_active(struct eth_device *dev)
int eth_send(void *packet, int length)
{
+ int ret;
+
if (!eth_current)
return -ENODEV;
- return eth_current->send(eth_current, packet, length);
+ ret = eth_current->send(eth_current, packet, length);
+#if defined(CONFIG_CMD_PCAP)
+ if (ret >= 0)
+ pcap_post(packet, lengeth, true);
+#endif
+ return ret;
}
int eth_rx(void)
diff --git a/net/mdio-uclass.c b/net/mdio-uclass.c
index 36a404ff44..6f922e80b6 100644
--- a/net/mdio-uclass.c
+++ b/net/mdio-uclass.c
@@ -23,6 +23,17 @@ void dm_mdio_probe_devices(void)
static int dm_mdio_post_bind(struct udevice *dev)
{
+ const char *dt_name;
+
+ /* set a custom name for the MDIO device, if present in DT */
+ if (ofnode_valid(dev->node)) {
+ dt_name = ofnode_read_string(dev->node, "device-name");
+ if (dt_name) {
+ debug("renaming dev %s to %s\n", dev->name, dt_name);
+ device_set_name(dev, dt_name);
+ }
+ }
+
/*
* MDIO command doesn't like spaces in names, don't allow them to keep
* it happy
@@ -75,7 +86,7 @@ static int dm_mdio_post_probe(struct udevice *dev)
pdata->mii_bus->write = mdio_write;
pdata->mii_bus->reset = mdio_reset;
pdata->mii_bus->priv = dev;
- strncpy(pdata->mii_bus->name, dev->name, MDIO_NAME_LEN);
+ strncpy(pdata->mii_bus->name, dev->name, MDIO_NAME_LEN - 1);
return mdio_register(pdata->mii_bus);
}
diff --git a/net/net.c b/net/net.c
index 40511db645..ded86e7456 100644
--- a/net/net.c
+++ b/net/net.c
@@ -96,6 +96,9 @@
#include <net.h>
#include <net/fastboot.h>
#include <net/tftp.h>
+#if defined(CONFIG_CMD_PCAP)
+#include <net/pcap.h>
+#endif
#if defined(CONFIG_LED_STATUS)
#include <miiphy.h>
#include <status_led.h>
@@ -672,6 +675,11 @@ done:
net_set_icmp_handler(NULL);
#endif
net_set_state(prev_net_state);
+
+#if defined(CONFIG_CMD_PCAP)
+ if (pcap_active())
+ pcap_print_status();
+#endif
return ret;
}
@@ -1084,6 +1092,9 @@ void net_process_received_packet(uchar *in_packet, int len)
debug_cond(DEBUG_NET_PKT, "packet received\n");
+#if defined(CONFIG_CMD_PCAP)
+ pcap_post(in_packet, len, false);
+#endif
net_rx_packet = in_packet;
net_rx_packet_len = len;
et = (struct ethernet_hdr *)in_packet;
@@ -1253,6 +1264,9 @@ void net_process_received_packet(uchar *in_packet, int len)
return;
}
+ if (ntohs(ip->udp_len) < UDP_HDR_SIZE || ntohs(ip->udp_len) > ntohs(ip->ip_len))
+ return;
+
debug_cond(DEBUG_DEV_PKT,
"received UDP (to=%pI4, from=%pI4, len=%d)\n",
&dst_ip, &src_ip, len);
diff --git a/net/nfs.c b/net/nfs.c
index d6a7f8e827..aca0ca55f3 100644
--- a/net/nfs.c
+++ b/net/nfs.c
@@ -196,10 +196,10 @@ static void rpc_req(int rpc_prog, int rpc_proc, uint32_t *data, int datalen)
rpc_pkt.u.call.vers = htonl(2); /* portmapper is version 2 */
}
rpc_pkt.u.call.proc = htonl(rpc_proc);
- p = (uint32_t *)&(rpc_pkt.u.call.data);
+ p = rpc_pkt.u.call.data;
if (datalen)
- memcpy((char *)p, (char *)data, datalen*sizeof(uint32_t));
+ memcpy(p, data, datalen * sizeof(uint32_t));
pktlen = (char *)p + datalen * sizeof(uint32_t) - (char *)&rpc_pkt;
@@ -566,11 +566,15 @@ static int nfs_lookup_reply(uchar *pkt, unsigned len)
}
if (supported_nfs_versions & NFSV2_FLAG) {
+ if (((uchar *)&(rpc_pkt.u.reply.data[0]) - (uchar *)(&rpc_pkt) + NFS_FHSIZE) > len)
+ return -NFS_RPC_DROP;
memcpy(filefh, rpc_pkt.u.reply.data + 1, NFS_FHSIZE);
} else { /* NFSV3_FLAG */
filefh3_length = ntohl(rpc_pkt.u.reply.data[1]);
if (filefh3_length > NFS3_FHSIZE)
filefh3_length = NFS3_FHSIZE;
+ if (((uchar *)&(rpc_pkt.u.reply.data[0]) - (uchar *)(&rpc_pkt) + filefh3_length) > len)
+ return -NFS_RPC_DROP;
memcpy(filefh, rpc_pkt.u.reply.data + 2, filefh3_length);
}
@@ -579,7 +583,7 @@ static int nfs_lookup_reply(uchar *pkt, unsigned len)
static int nfs3_get_attributes_offset(uint32_t *data)
{
- if (ntohl(data[1]) != 0) {
+ if (data[1]) {
/* 'attributes_follow' flag is TRUE,
* so we have attributes on 21 dwords */
/* Skip unused values :
@@ -634,6 +638,9 @@ static int nfs_readlink_reply(uchar *pkt, unsigned len)
/* new path length */
rlen = ntohl(rpc_pkt.u.reply.data[1 + nfsv3_data_offset]);
+ if (((uchar *)&(rpc_pkt.u.reply.data[0]) - (uchar *)(&rpc_pkt) + rlen) > len)
+ return -NFS_RPC_DROP;
+
if (*((char *)&(rpc_pkt.u.reply.data[2 + nfsv3_data_offset])) != '/') {
int pathlen;
@@ -701,6 +708,9 @@ static int nfs_read_reply(uchar *pkt, unsigned len)
&(rpc_pkt.u.reply.data[4 + nfsv3_data_offset]);
}
+ if (((uchar *)&(rpc_pkt.u.reply.data[0]) - (uchar *)(&rpc_pkt) + rlen) > len)
+ return -9999;
+
if (store_block(data_ptr, nfs_offset, rlen))
return -9999;
@@ -732,6 +742,9 @@ static void nfs_handler(uchar *pkt, unsigned dest, struct in_addr sip,
debug("%s\n", __func__);
+ if (len > sizeof(struct rpc_t))
+ return;
+
if (dest != nfs_our_port)
return;
diff --git a/net/nfs.h b/net/nfs.h
index a377c90088..68ada0efeb 100644
--- a/net/nfs.h
+++ b/net/nfs.h
@@ -78,7 +78,7 @@ struct rpc_t {
NFS_MAX_ATTRS];
} reply;
} u;
-} __attribute__((packed));
+};
void nfs_start(void); /* Begin NFS */
diff --git a/net/pcap.c b/net/pcap.c
new file mode 100644
index 0000000000..4036d8a3fa
--- /dev/null
+++ b/net/pcap.c
@@ -0,0 +1,156 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2019 Ramon Fried <rfried.dev@gmail.com>
+ */
+
+#include <common.h>
+#include <net.h>
+#include <net/pcap.h>
+#include <time.h>
+#include <asm/io.h>
+
+#define LINKTYPE_ETHERNET 1
+
+static bool initialized;
+static bool running;
+static bool buffer_full;
+static void *buf;
+static unsigned int max_size;
+static unsigned int pos;
+
+static unsigned long incoming_count;
+static unsigned long outgoing_count;
+
+struct pcap_header {
+ u32 magic;
+ u16 version_major;
+ u16 version_minor;
+ s32 thiszone;
+ u32 sigfigs;
+ u32 snaplen;
+ u32 network;
+};
+
+struct pcap_packet_header {
+ u32 ts_sec;
+ u32 ts_usec;
+ u32 incl_len;
+ u32 orig_len;
+};
+
+static struct pcap_header file_header = {
+ .magic = 0xa1b2c3d4,
+ .version_major = 2,
+ .version_minor = 4,
+ .snaplen = 65535,
+ .network = LINKTYPE_ETHERNET,
+};
+
+int pcap_init(phys_addr_t paddr, unsigned long size)
+{
+ buf = map_physmem(paddr, size, 0);
+ if (!buf) {
+ printf("Failed mapping PCAP memory\n");
+ return -ENOMEM;
+ }
+
+ printf("PCAP capture initialized: addr: 0x%lx max length: %lu\n",
+ (unsigned long)buf, size);
+
+ memcpy(buf, &file_header, sizeof(file_header));
+ pos = sizeof(file_header);
+ max_size = size;
+ initialized = true;
+ running = false;
+ buffer_full = false;
+ incoming_count = 0;
+ outgoing_count = 0;
+ return 0;
+}
+
+int pcap_start_stop(bool start)
+{
+ if (!initialized) {
+ printf("error: pcap was not initialized\n");
+ return -ENODEV;
+ }
+
+ running = start;
+
+ return 0;
+}
+
+int pcap_clear(void)
+{
+ if (!initialized) {
+ printf("error: pcap was not initialized\n");
+ return -ENODEV;
+ }
+
+ pos = sizeof(file_header);
+ incoming_count = 0;
+ outgoing_count = 0;
+ buffer_full = false;
+
+ printf("pcap capture cleared\n");
+ return 0;
+}
+
+int pcap_post(const void *packet, size_t len, bool outgoing)
+{
+ struct pcap_packet_header header;
+ u64 cur_time = timer_get_us();
+
+ if (!initialized || !running || !buf)
+ return -ENODEV;
+
+ if (buffer_full)
+ return -ENOMEM;
+
+ if ((pos + len + sizeof(header)) >= max_size) {
+ buffer_full = true;
+ printf("\n!!! Buffer is full, consider increasing buffer size !!!\n");
+ return -ENOMEM;
+ }
+
+ header.ts_sec = cur_time / 1000000;
+ header.ts_usec = cur_time % 1000000;
+ header.incl_len = len;
+ header.orig_len = len;
+
+ memcpy(buf + pos, &header, sizeof(header));
+ pos += sizeof(header);
+ memcpy(buf + pos, packet, len);
+ pos += len;
+
+ if (outgoing)
+ outgoing_count++;
+ else
+ incoming_count++;
+
+ env_set_hex("pcapsize", pos);
+
+ return 0;
+}
+
+int pcap_print_status(void)
+{
+ if (!initialized) {
+ printf("pcap was not initialized\n");
+ return -ENODEV;
+ }
+ printf("PCAP status:\n");
+ printf("\tInitialized addr: 0x%lx\tmax length: %u\n",
+ (unsigned long)buf, max_size);
+ printf("\tStatus: %s.\t file size: %u\n", running ? "Active" : "Idle",
+ pos);
+ printf("\tIncoming packets: %lu Outgoing packets: %lu\n",
+ incoming_count, outgoing_count);
+
+ return 0;
+}
+
+bool pcap_active(void)
+{
+ return running;
+}