- Assorted CVE fixes
- Other fixes
This commit is contained in:
Tom Rini 2019-09-04 16:02:03 -04:00
commit ece9834f7d
39 changed files with 911 additions and 57 deletions

View File

@ -1025,6 +1025,17 @@ ifneq ($(CONFIG_WDT),y)
@echo >&2 "See doc/driver-model/MIGRATION.txt for more info."
@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

View File

@ -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

View File

@ -96,6 +96,7 @@
#size-cells = <0>;
compatible = "marvell,orion-mdio";
reg = <0x12a200 0x10>;
device-name = "cpm-mdio";
};
cpm_syscon0: system-controller@440000 {

View File

@ -96,6 +96,7 @@
#size-cells = <0>;
compatible = "marvell,orion-mdio";
reg = <0x12a200 0x10>;
device-name = "cps-mdio";
};
cps_syscon0: system-controller@440000 {

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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,

71
cmd/pcap.c Normal file
View File

@ -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),
);

View File

@ -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

62
doc/README.pcap Normal file
View File

@ -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

View File

@ -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.

View File

@ -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>;
};
};

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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" },

View File

@ -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;

View File

@ -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

View File

@ -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);

View File

@ -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)) {

View File

@ -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),
};

View File

@ -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;

236
drivers/net/mvmdio.c Normal file
View File

@ -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),
};

View File

@ -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 = {

View File

@ -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)

View File

@ -42,7 +42,7 @@
#define DNS_CALLBACK
#endif
#ifdef CONFIG_CMD_NET
#ifdef CONFIG_NET
#define NET_CALLBACKS \
"bootfile:bootfile," \
"ipaddr:ipaddr," \

View File

@ -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

View File

@ -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);

55
include/net/pcap.h Normal file
View File

@ -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);

View File

@ -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 */

View File

@ -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

View File

@ -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;
}

View File

@ -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)

View File

@ -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);
}

View File

@ -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);

View File

@ -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;

View File

@ -78,7 +78,7 @@ struct rpc_t {
NFS_MAX_ATTRS];
} reply;
} u;
} __attribute__((packed));
};
void nfs_start(void); /* Begin NFS */

156
net/pcap.c Normal file
View File

@ -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;
}