diff options
82 files changed, 1699 insertions, 282 deletions
@@ -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/Kconfig b/arch/Kconfig index f4ada57909..141e48bc43 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -137,6 +137,7 @@ config SANDBOX config SH bool "SuperH architecture" select HAVE_PRIVATE_LIBGCC + select SUPPORT_OF_CONTROL config X86 bool "x86 architecture" 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/arch/arm/mach-bcm283x/Kconfig b/arch/arm/mach-bcm283x/Kconfig index 3eb5a9a897..b08275f598 100644 --- a/arch/arm/mach-bcm283x/Kconfig +++ b/arch/arm/mach-bcm283x/Kconfig @@ -26,6 +26,23 @@ config BCM2837_64B select BCM2837 select ARM64 +config BCM2711 + bool "Broadcom BCM2711 SoC support" + depends on ARCH_BCM283X + +config BCM2711_32B + bool "Broadcom BCM2711 SoC 32-bit support" + depends on ARCH_BCM283X + select BCM2711 + select ARMV7_LPAE + select CPU_V7A + +config BCM2711_64B + bool "Broadcom BCM2711 SoC 64-bit support" + depends on ARCH_BCM283X + select BCM2711 + select ARM64 + menu "Broadcom BCM283X family" depends on ARCH_BCM283X @@ -127,6 +144,50 @@ config TARGET_RPI_3 This option creates a build targeting the ARMv8/AArch64 ISA. select BCM2837_64B +config TARGET_RPI_4_32B + bool "Raspberry Pi 4 32-bit build" + help + Support for all BCM2711-based Raspberry Pi variants, such as + the RPi 4 model B, in AArch32 (32-bit) mode. + + This option assumes the VideoCore firmware is configured to use the + mini UART (rather than PL011) for the serial console. This is the + default on the RPi 4. To enable the UART console, the following non- + default option must be present in config.txt: enable_uart=1. This is + required for U-Boot to operate correctly, even if you only care + about the HDMI/usbkbd console. + + Due to hardware incompatibilities, this can't be used with + BCM283/5/6/7. + + This option creates a build targeting the ARMv7/AArch32 ISA. + select BCM2711_32B + +config TARGET_RPI_4 + bool "Raspberry Pi 4 64-bit build" + help + Support for all BCM2711-based Raspberry Pi variants, such as + the RPi 4 model B, in AArch64 (64-bit) mode. + + This option assumes the VideoCore firmware is configured to use the + mini UART (rather than PL011) for the serial console. This is the + default on the RPi 4. To enable the UART console, the following non- + default option must be present in config.txt: enable_uart=1. This is + required for U-Boot to operate correctly, even if you only care + about the HDMI/usbkbd console. + + Due to hardware incompatibilities, this can't be used with + BCM283/5/6/7. + + Also, due to a bug in firmware, switching to 64bit mode doesn't + happen automatically based on the kernel's image filename. See + https://github.com/raspberrypi/firmware/issues/1193 for more details. + Until that is resolved, the configuration (config.txt) needs to + explicitly set: arm_64bit=1. + + This option creates a build targeting the ARMv8/AArch64 ISA. + select BCM2711_64B + endchoice config SYS_BOARD @@ -141,4 +202,10 @@ config SYS_SOC config SYS_CONFIG_NAME default "rpi" +config BCM283x_BASE + hex + default "0x20000000" if BCM2835 + default "0x3f000000" if BCM2836 || BCM2837 + default "0xfe000000" if BCM2711 + endmenu diff --git a/arch/arm/mach-bcm283x/include/mach/mbox.h b/arch/arm/mach-bcm283x/include/mach/mbox.h index e3a893e49c..0b6c2543d5 100644 --- a/arch/arm/mach-bcm283x/include/mach/mbox.h +++ b/arch/arm/mach-bcm283x/include/mach/mbox.h @@ -37,18 +37,17 @@ /* Raw mailbox HW */ -#ifndef CONFIG_BCM2835 -#define BCM2835_MBOX_PHYSADDR 0x3f00b880 -#else -#define BCM2835_MBOX_PHYSADDR 0x2000b880 -#endif +#define BCM2835_MBOX_PHYSADDR (CONFIG_BCM283x_BASE + 0x0000b880) struct bcm2835_mbox_regs { u32 read; u32 rsvd0[5]; - u32 status; - u32 config; + u32 mail0_status; + u32 mail0_config; u32 write; + u32 rsvd1[5]; + u32 mail1_status; + u32 mail1_config; }; #define BCM2835_MBOX_STATUS_WR_FULL 0x80000000 @@ -234,6 +233,7 @@ struct bcm2835_mbox_tag_set_power_state { #define BCM2835_MBOX_CLOCK_ID_SDRAM 8 #define BCM2835_MBOX_CLOCK_ID_PIXEL 9 #define BCM2835_MBOX_CLOCK_ID_PWM 10 +#define BCM2835_MBOX_CLOCK_ID_EMMC2 12 struct bcm2835_mbox_tag_get_clock_rate { struct bcm2835_mbox_tag_hdr tag_hdr; diff --git a/arch/arm/mach-bcm283x/include/mach/sdhci.h b/arch/arm/mach-bcm283x/include/mach/sdhci.h index 5cb6ec3340..b443c379d8 100644 --- a/arch/arm/mach-bcm283x/include/mach/sdhci.h +++ b/arch/arm/mach-bcm283x/include/mach/sdhci.h @@ -6,11 +6,7 @@ #ifndef _BCM2835_SDHCI_H_ #define _BCM2835_SDHCI_H_ -#ifndef CONFIG_BCM2835 -#define BCM2835_SDHCI_BASE 0x3f300000 -#else -#define BCM2835_SDHCI_BASE 0x20300000 -#endif +#define BCM2835_SDHCI_BASE (CONFIG_BCM283x_BASE + 0x00300000) int bcm2835_sdhci_init(u32 regbase, u32 emmc_freq); diff --git a/arch/arm/mach-bcm283x/include/mach/timer.h b/arch/arm/mach-bcm283x/include/mach/timer.h index 56b0c356bb..014355e759 100644 --- a/arch/arm/mach-bcm283x/include/mach/timer.h +++ b/arch/arm/mach-bcm283x/include/mach/timer.h @@ -6,11 +6,7 @@ #ifndef _BCM2835_TIMER_H #define _BCM2835_TIMER_H -#ifndef CONFIG_BCM2835 -#define BCM2835_TIMER_PHYSADDR 0x3f003000 -#else -#define BCM2835_TIMER_PHYSADDR 0x20003000 -#endif +#define BCM2835_TIMER_PHYSADDR (CONFIG_BCM283x_BASE + 0x00003000) #define BCM2835_TIMER_CS_M3 (1 << 3) #define BCM2835_TIMER_CS_M2 (1 << 2) diff --git a/arch/arm/mach-bcm283x/include/mach/wdog.h b/arch/arm/mach-bcm283x/include/mach/wdog.h index 99c88e5df7..8292b3cf1f 100644 --- a/arch/arm/mach-bcm283x/include/mach/wdog.h +++ b/arch/arm/mach-bcm283x/include/mach/wdog.h @@ -6,11 +6,7 @@ #ifndef _BCM2835_WDOG_H #define _BCM2835_WDOG_H -#ifndef CONFIG_BCM2835 -#define BCM2835_WDOG_PHYSADDR 0x3f100000 -#else -#define BCM2835_WDOG_PHYSADDR 0x20100000 -#endif +#define BCM2835_WDOG_PHYSADDR (CONFIG_BCM283x_BASE + 0x00100000) struct bcm2835_wdog_regs { u32 unknown0[7]; diff --git a/arch/arm/mach-bcm283x/mbox.c b/arch/arm/mach-bcm283x/mbox.c index 1642ebd103..3c67f68c17 100644 --- a/arch/arm/mach-bcm283x/mbox.c +++ b/arch/arm/mach-bcm283x/mbox.c @@ -27,7 +27,7 @@ int bcm2835_mbox_call_raw(u32 chan, u32 send, u32 *recv) /* Drain any stale responses */ for (;;) { - val = readl(®s->status); + val = readl(®s->mail0_status); if (val & BCM2835_MBOX_STATUS_RD_EMPTY) break; if (get_timer(0) >= endtime) { @@ -40,7 +40,7 @@ int bcm2835_mbox_call_raw(u32 chan, u32 send, u32 *recv) /* Wait for space to send */ for (;;) { - val = readl(®s->status); + val = readl(®s->mail1_status); if (!(val & BCM2835_MBOX_STATUS_WR_FULL)) break; if (get_timer(0) >= endtime) { @@ -58,7 +58,7 @@ int bcm2835_mbox_call_raw(u32 chan, u32 send, u32 *recv) /* Wait for the response */ for (;;) { - val = readl(®s->status); + val = readl(®s->mail0_status); if (!(val & BCM2835_MBOX_STATUS_RD_EMPTY)) break; if (get_timer(0) >= endtime) { diff --git a/arch/sh/cpu/u-boot.lds b/arch/sh/cpu/u-boot.lds index 7b225a6bd9..47302da252 100644 --- a/arch/sh/cpu/u-boot.lds +++ b/arch/sh/cpu/u-boot.lds @@ -75,6 +75,7 @@ SECTIONS PROVIDE (__init_end = .); PROVIDE (reloc_dst_end = .); + PROVIDE (_end = .); PROVIDE (bss_start = .); PROVIDE (__bss_start = .); diff --git a/arch/sh/dts/Makefile b/arch/sh/dts/Makefile new file mode 100644 index 0000000000..e423bfd566 --- /dev/null +++ b/arch/sh/dts/Makefile @@ -0,0 +1,12 @@ +dtb-y += sh7751-r2dplus.dtb + +targets += $(dtb-y) + +# Add any required device tree compiler flags here +DTC_FLAGS += + +PHONY += dtbs +dtbs: $(addprefix $(obj)/, $(dtb-y)) + @: + +clean-files := *.dtb *_HS diff --git a/arch/sh/dts/sh7751-r2dplus.dts b/arch/sh/dts/sh7751-r2dplus.dts new file mode 100644 index 0000000000..ecaf0772d8 --- /dev/null +++ b/arch/sh/dts/sh7751-r2dplus.dts @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Device Tree Source for the SH7751 R2Dplus + * + * Copyright (C) 2019 Marek Vasut <marek.vasut@gmail.com> + */ + +/dts-v1/; +/ { + model = "R2D"; + compatible = "renesas,r2d", "renesas,sh7751"; + + pci@fe200000 { + compatible = "renesas,pci-sh7751"; + device_type = "pci"; + reg = <0 0xfe200000 0 0x1000>; + status = "okay"; + + bus-range = <0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + ranges = <0x01000000 0 0xfe240000 0 0xfe240000 0 0x00040000 + 0x02000000 0 0xfd000000 0 0xfd000000 0 0x01000000>; + }; +}; diff --git a/arch/sh/include/asm/config.h b/arch/sh/include/asm/config.h index df38c82abc..e1cd322152 100644 --- a/arch/sh/include/asm/config.h +++ b/arch/sh/include/asm/config.h @@ -8,9 +8,11 @@ #include <asm/processor.h> +#define CONFIG_LMB + /* Timer */ #define CONFIG_SYS_TIMER_COUNTS_DOWN -#define CONFIG_SYS_TIMER_COUNTER (TMU_BASE + 0x8) /* TCNT0 */ +#define CONFIG_SYS_TIMER_COUNTER (TMU_BASE + 0xc) /* TCNT0 */ #define CONFIG_SYS_TIMER_RATE (CONFIG_SYS_CLK_FREQ / 4) #endif diff --git a/arch/sh/lib/start.S b/arch/sh/lib/start.S index f5350b9064..f9f26d3779 100644 --- a/arch/sh/lib/start.S +++ b/arch/sh/lib/start.S @@ -22,6 +22,17 @@ _start: mov.l ._reloc_dst, r4 add #(_start-1b), r5 mov.l ._reloc_dst_end, r6 +#ifdef CONFIG_OF_SEPARATE + mov.l ._reloc_size, r0 + add r5, r0 + add #4, r0 + mov.l @r0, r0 + swap.b r0, r0 + swap.w r0, r0 + swap.b r0, r0 + add #4, r0 + add r0, r6 +#endif 2: mov.l @r5+, r1 mov.l r1, @r4 @@ -29,6 +40,7 @@ _start: cmp/hs r6, r4 bf 2b +#ifndef CONFIG_OF_SEPARATE mov.l ._bss_start, r4 mov.l ._bss_end, r5 mov #0, r1 @@ -37,6 +49,7 @@ _start: add #4, r4 cmp/hs r5, r4 bf 3b +#endif mov.l ._gd_init, r13 /* global data */ mov.l ._stack_init, r15 /* stack */ @@ -53,6 +66,7 @@ loop: ._lowlevel_init: .long (lowlevel_init - (100b + 4)) ._reloc_dst: .long _start ._reloc_dst_end: .long reloc_dst_end +._reloc_size: .long (_end - _start) ._bss_start: .long bss_start ._bss_end: .long bss_end ._gd_init: .long (_start - GENERATED_GBL_DATA_SIZE) diff --git a/board/raspberrypi/rpi/rpi.c b/board/raspberrypi/rpi/rpi.c index 7a6ca8f759..fa57d50c95 100644 --- a/board/raspberrypi/rpi/rpi.c +++ b/board/raspberrypi/rpi/rpi.c @@ -148,6 +148,11 @@ static const struct rpi_model rpi_models_new_scheme[] = { DTB_DIR "bcm2837-rpi-cm3.dtb", false, }, + [0x11] = { + "4 Model B", + DTB_DIR "bcm2711-rpi-4-b.dtb", + true, + }, }; static const struct rpi_model rpi_models_old_scheme[] = { @@ -244,7 +249,8 @@ static uint32_t rev_type; static const struct rpi_model *model; #ifdef CONFIG_ARM64 -static struct mm_region bcm2837_mem_map[] = { +#ifndef CONFIG_BCM2711 +static struct mm_region bcm283x_mem_map[] = { { .virt = 0x00000000UL, .phys = 0x00000000UL, @@ -263,8 +269,28 @@ static struct mm_region bcm2837_mem_map[] = { 0, } }; - -struct mm_region *mem_map = bcm2837_mem_map; +#else +static struct mm_region bcm283x_mem_map[] = { + { + .virt = 0x00000000UL, + .phys = 0x00000000UL, + .size = 0xfe000000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_INNER_SHARE + }, { + .virt = 0xfe000000UL, + .phys = 0xfe000000UL, + .size = 0x01800000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, { + /* List terminator */ + 0, + } +}; +#endif +struct mm_region *mem_map = bcm283x_mem_map; #endif int dram_init(void) diff --git a/board/renesas/r2dplus/r2dplus.c b/board/renesas/r2dplus/r2dplus.c index f0773267b1..6eff98706f 100644 --- a/board/renesas/r2dplus/r2dplus.c +++ b/board/renesas/r2dplus/r2dplus.c @@ -9,7 +9,6 @@ #include <netdev.h> #include <asm/processor.h> #include <asm/io.h> -#include <asm/pci.h> int checkboard(void) { @@ -45,12 +44,6 @@ void ide_set_reset(int idereset) } } -static struct pci_controller hose; -void pci_init_board(void) -{ - pci_sh7751_init(&hose); -} - int board_eth_init(bd_t *bis) { return pci_eth_init(bis); 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, ®lo, ®hi)) 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/evb-ast2500_defconfig b/configs/evb-ast2500_defconfig index b47ca5b52a..299fbfe94a 100644 --- a/configs/evb-ast2500_defconfig +++ b/configs/evb-ast2500_defconfig @@ -24,7 +24,6 @@ CONFIG_REGMAP=y CONFIG_CLK=y CONFIG_DM_I2C=y CONFIG_SYS_I2C_ASPEED=y -# CONFIG_MMC is not set CONFIG_PHY_REALTEK=y CONFIG_DM_ETH=y CONFIG_FTGMAC100=y diff --git a/configs/qemu-riscv32_defconfig b/configs/qemu-riscv32_defconfig index d5b33b5c2b..fe09a0da88 100644 --- a/configs/qemu-riscv32_defconfig +++ b/configs/qemu-riscv32_defconfig @@ -5,5 +5,6 @@ CONFIG_DISTRO_DEFAULTS=y CONFIG_FIT=y CONFIG_DISPLAY_CPUINFO=y CONFIG_DISPLAY_BOARDINFO=y +CONFIG_CMD_BOOTEFI_SELFTEST=y # CONFIG_CMD_MII is not set CONFIG_OF_PRIOR_STAGE=y diff --git a/configs/qemu-riscv32_smode_defconfig b/configs/qemu-riscv32_smode_defconfig index a80e68b8c7..7103324421 100644 --- a/configs/qemu-riscv32_smode_defconfig +++ b/configs/qemu-riscv32_smode_defconfig @@ -6,5 +6,6 @@ CONFIG_DISTRO_DEFAULTS=y CONFIG_FIT=y CONFIG_DISPLAY_CPUINFO=y CONFIG_DISPLAY_BOARDINFO=y +CONFIG_CMD_BOOTEFI_SELFTEST=y # CONFIG_CMD_MII is not set CONFIG_OF_PRIOR_STAGE=y diff --git a/configs/qemu-riscv64_defconfig b/configs/qemu-riscv64_defconfig index 19a5849226..ef84dfded2 100644 --- a/configs/qemu-riscv64_defconfig +++ b/configs/qemu-riscv64_defconfig @@ -6,5 +6,6 @@ CONFIG_DISTRO_DEFAULTS=y CONFIG_FIT=y CONFIG_DISPLAY_CPUINFO=y CONFIG_DISPLAY_BOARDINFO=y +CONFIG_CMD_BOOTEFI_SELFTEST=y # CONFIG_CMD_MII is not set CONFIG_OF_PRIOR_STAGE=y diff --git a/configs/qemu-riscv64_smode_defconfig b/configs/qemu-riscv64_smode_defconfig index 74743a5ebe..1c7a2d150c 100644 --- a/configs/qemu-riscv64_smode_defconfig +++ b/configs/qemu-riscv64_smode_defconfig @@ -7,5 +7,6 @@ CONFIG_DISTRO_DEFAULTS=y CONFIG_FIT=y CONFIG_DISPLAY_CPUINFO=y CONFIG_DISPLAY_BOARDINFO=y +CONFIG_CMD_BOOTEFI_SELFTEST=y # CONFIG_CMD_MII is not set CONFIG_OF_PRIOR_STAGE=y diff --git a/configs/r2dplus_defconfig b/configs/r2dplus_defconfig index 4c1912c8a1..b2334affc3 100644 --- a/configs/r2dplus_defconfig +++ b/configs/r2dplus_defconfig @@ -1,12 +1,14 @@ CONFIG_SH=y CONFIG_SYS_TEXT_BASE=0x8FE00000 CONFIG_TARGET_R2DPLUS=y +# CONFIG_SYS_MALLOC_F is not set CONFIG_BOOTDELAY=-1 CONFIG_USE_BOOTARGS=y CONFIG_BOOTARGS="console=ttySC0,115200" # CONFIG_CMDLINE_EDITING is not set # CONFIG_AUTO_COMPLETE is not set CONFIG_CMD_IMLS=y +CONFIG_CMD_DM=y CONFIG_CMD_IDE=y CONFIG_CMD_PCI=y # CONFIG_CMD_SETEXPR is not set @@ -14,11 +16,16 @@ CONFIG_CMD_PING=y CONFIG_CMD_CACHE=y CONFIG_CMD_EXT2=y CONFIG_DOS_PARTITION=y +CONFIG_OF_CONTROL=y +CONFIG_DEFAULT_DEVICE_TREE="sh7751-r2dplus" CONFIG_ENV_IS_IN_FLASH=y +CONFIG_DM=y CONFIG_MTD_NOR_FLASH=y CONFIG_FLASH_CFI_DRIVER=y CONFIG_SYS_FLASH_CFI=y CONFIG_RTL8139=y CONFIG_PCI=y +CONFIG_DM_PCI=y +CONFIG_DM_PCI_COMPAT=y CONFIG_SCIF_CONSOLE=y CONFIG_USE_PRIVATE_LIBGCC=y diff --git a/configs/rpi_4_32b_defconfig b/configs/rpi_4_32b_defconfig new file mode 100644 index 0000000000..a31a617a5f --- /dev/null +++ b/configs/rpi_4_32b_defconfig @@ -0,0 +1,33 @@ +CONFIG_ARM=y +CONFIG_ARCH_BCM283X=y +CONFIG_SYS_TEXT_BASE=0x00008000 +CONFIG_TARGET_RPI_4_32B=y +CONFIG_SYS_MALLOC_F_LEN=0x2000 +CONFIG_DISTRO_DEFAULTS=y +CONFIG_NR_DRAM_BANKS=1 +# CONFIG_ARCH_FIXUP_FDT_MEMORY is not set +CONFIG_OF_BOARD=y +CONFIG_OF_BOARD_SETUP=y +CONFIG_MISC_INIT_R=y +# CONFIG_DISPLAY_CPUINFO is not set +# CONFIG_DISPLAY_BOARDINFO is not set +CONFIG_SYS_PROMPT="U-Boot> " +# CONFIG_CMD_FLASH is not set +CONFIG_CMD_GPIO=y +CONFIG_CMD_MMC=y +CONFIG_CMD_FS_UUID=y +CONFIG_ENV_FAT_INTERFACE="mmc" +CONFIG_ENV_FAT_DEVICE_AND_PART="0:1" +CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y +CONFIG_DM_KEYBOARD=y +CONFIG_DM_MMC=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_BCM2835=y +CONFIG_PINCTRL=y +# CONFIG_PINCTRL_GENERIC is not set +# CONFIG_REQUIRE_SERIAL_CONSOLE is not set +CONFIG_DM_VIDEO=y +CONFIG_SYS_WHITE_ON_BLACK=y +CONFIG_CONSOLE_SCROLL_LINES=10 +CONFIG_PHYS_TO_BUS=y +CONFIG_OF_LIBFDT_OVERLAY=y diff --git a/configs/rpi_4_defconfig b/configs/rpi_4_defconfig new file mode 100644 index 0000000000..da8c960a2a --- /dev/null +++ b/configs/rpi_4_defconfig @@ -0,0 +1,33 @@ +CONFIG_ARM=y +CONFIG_ARCH_BCM283X=y +CONFIG_SYS_TEXT_BASE=0x00080000 +CONFIG_TARGET_RPI_4=y +CONFIG_SYS_MALLOC_F_LEN=0x2000 +CONFIG_DISTRO_DEFAULTS=y +CONFIG_NR_DRAM_BANKS=1 +# CONFIG_ARCH_FIXUP_FDT_MEMORY is not set +CONFIG_OF_BOARD=y +CONFIG_OF_BOARD_SETUP=y +CONFIG_MISC_INIT_R=y +# CONFIG_DISPLAY_CPUINFO is not set +# CONFIG_DISPLAY_BOARDINFO is not set +CONFIG_SYS_PROMPT="U-Boot> " +# CONFIG_CMD_FLASH is not set +CONFIG_CMD_GPIO=y +CONFIG_CMD_MMC=y +CONFIG_CMD_FS_UUID=y +CONFIG_ENV_FAT_INTERFACE="mmc" +CONFIG_ENV_FAT_DEVICE_AND_PART="0:1" +CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y +CONFIG_DM_KEYBOARD=y +CONFIG_DM_MMC=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_BCM2835=y +CONFIG_PINCTRL=y +# CONFIG_PINCTRL_GENERIC is not set +# CONFIG_REQUIRE_SERIAL_CONSOLE is not set +CONFIG_DM_VIDEO=y +CONFIG_SYS_WHITE_ON_BLACK=y +CONFIG_CONSOLE_SCROLL_LINES=10 +CONFIG_PHYS_TO_BUS=y +CONFIG_OF_LIBFDT_OVERLAY=y 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/api/efi.rst b/doc/api/efi.rst index 39e2dbae0b..2ca344932e 100644 --- a/doc/api/efi.rst +++ b/doc/api/efi.rst @@ -103,3 +103,36 @@ Block device driver .. kernel-doc:: lib/efi_driver/efi_block_device.c :internal: + +Protocols +--------- + +Block IO protocol +~~~~~~~~~~~~~~~~~ + +.. kernel-doc:: lib/efi_loader/efi_disk.c + :internal: + +File protocol +~~~~~~~~~~~~~ + +.. kernel-doc:: lib/efi_loader/efi_file.c + :internal: + +Graphical output protocol +~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. kernel-doc:: lib/efi_loader/efi_gop.c + :internal: + +Network protocols +~~~~~~~~~~~~~~~~~ + +.. kernel-doc:: lib/efi_loader/efi_net.c + :internal: + +Text IO protocols +~~~~~~~~~~~~~~~~~ + +.. kernel-doc:: lib/efi_loader/efi_console.c + :internal: 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/doc/git-mailrc b/doc/git-mailrc index a63b76befc..1d36f5845a 100644 --- a/doc/git-mailrc +++ b/doc/git-mailrc @@ -35,6 +35,7 @@ alias mariosix Mario Six <mario.six@gdsys.cc> alias masahiro Masahiro Yamada <yamada.masahiro@socionext.com> alias mateusz Mateusz Kulikowski <mateusz.kulikowski@gmail.com> alias maxime Maxime Ripard <maxime.ripard@free-electrons.com> +alias mbrugger Matthias Brugger <mbrugger@suse.com> alias monstr Michal Simek <monstr@monstr.eu> alias prom Minkyu Kang <mk7.kang@samsung.com> alias ptomsich Philipp Tomsich <philipp.tomsich@theobroma-systems.com> @@ -74,6 +75,9 @@ alias uniphier uboot, masahiro alias zynq uboot, monstr alias rockchip uboot, sjg, kevery, ptomsich +alias bcm283x uboot, mbrugger +alias rpi uboot, mbrugger + alias m68k uboot, alisonwang, angelo_ts alias coldfire m68k diff --git a/drivers/core/device.c b/drivers/core/device.c index 474c1642ee..05dadf98f9 100644 --- a/drivers/core/device.c +++ b/drivers/core/device.c @@ -526,6 +526,7 @@ static int device_get_device_tail(struct udevice *dev, int ret, return 0; } +#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA) /** * device_find_by_ofnode() - Return device associated with given ofnode * @@ -552,6 +553,7 @@ static int device_find_by_ofnode(ofnode node, struct udevice **devp) return -ENODEV; } +#endif int device_get_child(struct udevice *parent, int index, struct udevice **devp) { @@ -817,6 +819,7 @@ int device_set_name(struct udevice *dev, const char *name) return 0; } +#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA) bool device_is_compatible(struct udevice *dev, const char *compat) { return ofnode_device_is_compatible(dev_ofnode(dev), compat); @@ -879,3 +882,4 @@ int dev_enable_by_path(const char *path) return lists_bind_fdt(parent, node, NULL, false); } +#endif diff --git a/drivers/core/root.c b/drivers/core/root.c index aa5ca4087a..e85643819e 100644 --- a/drivers/core/root.c +++ b/drivers/core/root.c @@ -314,13 +314,6 @@ int dm_scan_fdt(const void *blob, bool pre_reloc_only) #endif return dm_scan_fdt_node(gd->dm_root, blob, 0, pre_reloc_only); } -#else -static int dm_scan_fdt_node(struct udevice *parent, const void *blob, - int offset, bool pre_reloc_only) -{ - return 0; -} -#endif static int dm_scan_fdt_ofnode_path(const char *path, bool pre_reloc_only) { @@ -360,6 +353,7 @@ int dm_extended_scan_fdt(const void *blob, bool pre_reloc_only) return ret; } +#endif __weak int dm_scan_other(bool pre_reloc_only) { diff --git a/drivers/core/util.c b/drivers/core/util.c index 60b939a924..7dc1a2af02 100644 --- a/drivers/core/util.c +++ b/drivers/core/util.c @@ -31,6 +31,7 @@ int list_count_items(struct list_head *head) return count; } +#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA) bool dm_ofnode_pre_reloc(ofnode node) { #if defined(CONFIG_SPL_BUILD) || defined(CONFIG_TPL_BUILD) @@ -56,3 +57,4 @@ bool dm_ofnode_pre_reloc(ofnode node) return false; #endif } +#endif diff --git a/drivers/mmc/bcm2835_sdhci.c b/drivers/mmc/bcm2835_sdhci.c index bf3304c4dc..bc9ee95fd5 100644 --- a/drivers/mmc/bcm2835_sdhci.c +++ b/drivers/mmc/bcm2835_sdhci.c @@ -178,12 +178,13 @@ static int bcm2835_sdhci_probe(struct udevice *dev) fdt_addr_t base; int emmc_freq; int ret; + int clock_id = (int)dev_get_driver_data(dev); base = devfdt_get_addr(dev); if (base == FDT_ADDR_T_NONE) return -EINVAL; - ret = bcm2835_get_mmc_clock(BCM2835_MBOX_CLOCK_ID_EMMC); + ret = bcm2835_get_mmc_clock(clock_id); if (ret < 0) { debug("%s: Failed to set MMC clock (err=%d)\n", __func__, ret); return ret; @@ -230,7 +231,14 @@ static int bcm2835_sdhci_probe(struct udevice *dev) } static const struct udevice_id bcm2835_sdhci_match[] = { - { .compatible = "brcm,bcm2835-sdhci" }, + { + .compatible = "brcm,bcm2835-sdhci", + .data = BCM2835_MBOX_CLOCK_ID_EMMC + }, + { + .compatible = "brcm,bcm2711-emmc2", + .data = BCM2835_MBOX_CLOCK_ID_EMMC2 + }, { /* sentinel */ } }; diff --git a/drivers/mmc/bcm2835_sdhost.c b/drivers/mmc/bcm2835_sdhost.c index 1ce019af57..7f70acaf39 100644 --- a/drivers/mmc/bcm2835_sdhost.c +++ b/drivers/mmc/bcm2835_sdhost.c @@ -234,7 +234,7 @@ static void bcm2835_reset_internal(struct bcm2835_host *host) static int bcm2835_wait_transfer_complete(struct bcm2835_host *host) { - int timediff = 0; + ulong tstart_ms = get_timer(0); while (1) { u32 edm, fsm; @@ -254,11 +254,13 @@ static int bcm2835_wait_transfer_complete(struct bcm2835_host *host) break; } - /* Error out after 100000 register reads (~1s) */ - if (timediff++ == 100000) { + /* Error out after ~1s */ + ulong tlapse_ms = get_timer(tstart_ms); + if ( tlapse_ms > 1000 /* ms */ ) { + dev_err(host->dev, - "wait_transfer_complete - still waiting after %d retries\n", - timediff); + "wait_transfer_complete - still waiting after %lu ms\n", + tlapse_ms); bcm2835_dumpregs(host); return -ETIMEDOUT; } 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/drivers/pci/pci_sh7751.c b/drivers/pci/pci_sh7751.c index 2f918f161a..53e1668c99 100644 --- a/drivers/pci/pci_sh7751.c +++ b/drivers/pci/pci_sh7751.c @@ -6,6 +6,7 @@ */ #include <common.h> +#include <dm.h> #include <pci.h> #include <asm/processor.h> #include <asm/io.h> @@ -19,82 +20,113 @@ #define SH7751_WCR3 (vu_long *)0xFF800010 #define SH7751_MCR (vu_long *)0xFF800014 #define SH7751_BCR3 (vu_short *)0xFF800050 -#define SH7751_PCICONF0 (vu_long *)0xFE200000 -#define SH7751_PCICONF1 (vu_long *)0xFE200004 -#define SH7751_PCICONF2 (vu_long *)0xFE200008 -#define SH7751_PCICONF3 (vu_long *)0xFE20000C -#define SH7751_PCICONF4 (vu_long *)0xFE200010 -#define SH7751_PCICONF5 (vu_long *)0xFE200014 -#define SH7751_PCICONF6 (vu_long *)0xFE200018 -#define SH7751_PCICR (vu_long *)0xFE200100 -#define SH7751_PCILSR0 (vu_long *)0xFE200104 -#define SH7751_PCILSR1 (vu_long *)0xFE200108 -#define SH7751_PCILAR0 (vu_long *)0xFE20010C -#define SH7751_PCILAR1 (vu_long *)0xFE200110 -#define SH7751_PCIMBR (vu_long *)0xFE2001C4 -#define SH7751_PCIIOBR (vu_long *)0xFE2001C8 -#define SH7751_PCIPINT (vu_long *)0xFE2001CC -#define SH7751_PCIPINTM (vu_long *)0xFE2001D0 -#define SH7751_PCICLKR (vu_long *)0xFE2001D4 -#define SH7751_PCIBCR1 (vu_long *)0xFE2001E0 -#define SH7751_PCIBCR2 (vu_long *)0xFE2001E4 -#define SH7751_PCIWCR1 (vu_long *)0xFE2001E8 -#define SH7751_PCIWCR2 (vu_long *)0xFE2001EC -#define SH7751_PCIWCR3 (vu_long *)0xFE2001F0 -#define SH7751_PCIMCR (vu_long *)0xFE2001F4 -#define SH7751_PCIBCR3 (vu_long *)0xFE2001F8 - -#define BCR1_BREQEN 0x00080000 -#define PCI_SH7751_ID 0x35051054 -#define PCI_SH7751R_ID 0x350E1054 -#define SH7751_PCICONF1_WCC 0x00000080 -#define SH7751_PCICONF1_PER 0x00000040 -#define SH7751_PCICONF1_BUM 0x00000004 -#define SH7751_PCICONF1_MES 0x00000002 +#define SH7751_PCICONF0 (vu_long *)0xFE200000 +#define SH7751_PCICONF1 (vu_long *)0xFE200004 +#define SH7751_PCICONF2 (vu_long *)0xFE200008 +#define SH7751_PCICONF3 (vu_long *)0xFE20000C +#define SH7751_PCICONF4 (vu_long *)0xFE200010 +#define SH7751_PCICONF5 (vu_long *)0xFE200014 +#define SH7751_PCICONF6 (vu_long *)0xFE200018 +#define SH7751_PCICR (vu_long *)0xFE200100 +#define SH7751_PCILSR0 (vu_long *)0xFE200104 +#define SH7751_PCILSR1 (vu_long *)0xFE200108 +#define SH7751_PCILAR0 (vu_long *)0xFE20010C +#define SH7751_PCILAR1 (vu_long *)0xFE200110 +#define SH7751_PCIMBR (vu_long *)0xFE2001C4 +#define SH7751_PCIIOBR (vu_long *)0xFE2001C8 +#define SH7751_PCIPINT (vu_long *)0xFE2001CC +#define SH7751_PCIPINTM (vu_long *)0xFE2001D0 +#define SH7751_PCICLKR (vu_long *)0xFE2001D4 +#define SH7751_PCIBCR1 (vu_long *)0xFE2001E0 +#define SH7751_PCIBCR2 (vu_long *)0xFE2001E4 +#define SH7751_PCIWCR1 (vu_long *)0xFE2001E8 +#define SH7751_PCIWCR2 (vu_long *)0xFE2001EC +#define SH7751_PCIWCR3 (vu_long *)0xFE2001F0 +#define SH7751_PCIMCR (vu_long *)0xFE2001F4 +#define SH7751_PCIBCR3 (vu_long *)0xFE2001F8 + +#define BCR1_BREQEN 0x00080000 +#define PCI_SH7751_ID 0x35051054 +#define PCI_SH7751R_ID 0x350E1054 +#define SH7751_PCICONF1_WCC 0x00000080 +#define SH7751_PCICONF1_PER 0x00000040 +#define SH7751_PCICONF1_BUM 0x00000004 +#define SH7751_PCICONF1_MES 0x00000002 #define SH7751_PCICONF1_CMDS 0x000000C6 #define SH7751_PCI_HOST_BRIDGE 0x6 -#define SH7751_PCICR_PREFIX 0xa5000000 -#define SH7751_PCICR_PRST 0x00000002 -#define SH7751_PCICR_CFIN 0x00000001 -#define SH7751_PCIPINT_D3 0x00000002 -#define SH7751_PCIPINT_D0 0x00000001 -#define SH7751_PCICLKR_PREFIX 0xa5000000 +#define SH7751_PCICR_PREFIX 0xa5000000 +#define SH7751_PCICR_PRST 0x00000002 +#define SH7751_PCICR_CFIN 0x00000001 +#define SH7751_PCIPINT_D3 0x00000002 +#define SH7751_PCIPINT_D0 0x00000001 +#define SH7751_PCICLKR_PREFIX 0xa5000000 -#define SH7751_PCI_MEM_BASE 0xFD000000 -#define SH7751_PCI_MEM_SIZE 0x01000000 -#define SH7751_PCI_IO_BASE 0xFE240000 -#define SH7751_PCI_IO_SIZE 0x00040000 +#define SH7751_PCI_MEM_BASE 0xFD000000 +#define SH7751_PCI_MEM_SIZE 0x01000000 +#define SH7751_PCI_IO_BASE 0xFE240000 +#define SH7751_PCI_IO_SIZE 0x00040000 -#define SH7751_PCIPAR (vu_long *)0xFE2001C0 -#define SH7751_PCIPDR (vu_long *)0xFE200220 +#define SH7751_PCIPAR (vu_long *)0xFE2001C0 +#define SH7751_PCIPDR (vu_long *)0xFE200220 #define p4_in(addr) (*addr) #define p4_out(data, addr) (*addr) = (data) -/* Double word */ -int pci_sh4_read_config_dword(struct pci_controller *hose, - pci_dev_t dev, int offset, u32 *value) +static int sh7751_pci_addr_valid(pci_dev_t d, uint offset) { - u32 par_data = 0x80000000 | dev; + if (PCI_FUNC(d)) + return -EINVAL; - p4_out(par_data | (offset & 0xfc), SH7751_PCIPAR); - *value = p4_in(SH7751_PCIPDR); + return 0; +} + +static u32 get_bus_address(struct udevice *dev, pci_dev_t bdf, u32 offset) +{ + return BIT(31) | (PCI_DEV(bdf) << 8) | (offset & ~3); +} + +static int sh7751_pci_read_config(struct udevice *dev, pci_dev_t bdf, + uint offset, ulong *value, + enum pci_size_t size) +{ + u32 addr, reg; + int ret; + + ret = sh7751_pci_addr_valid(bdf, offset); + if (ret) { + *value = pci_get_ff(size); + return 0; + } + + addr = get_bus_address(dev, bdf, offset); + p4_out(addr, SH7751_PCIPAR); + reg = p4_in(SH7751_PCIPDR); + *value = pci_conv_32_to_size(reg, offset, size); return 0; } -int pci_sh4_write_config_dword(struct pci_controller *hose, - pci_dev_t dev, int offset, u32 value) +static int sh7751_pci_write_config(struct udevice *dev, pci_dev_t bdf, + uint offset, ulong value, + enum pci_size_t size) { - u32 par_data = 0x80000000 | dev; + u32 addr, reg, old; + int ret; - p4_out(par_data | (offset & 0xfc), SH7751_PCIPAR); - p4_out(value, SH7751_PCIPDR); + ret = sh7751_pci_addr_valid(bdf, offset); + if (ret) + return ret; + + addr = get_bus_address(dev, bdf, offset); + p4_out(addr, SH7751_PCIPAR); + old = p4_in(SH7751_PCIPDR); + reg = pci_conv_size_to_32(old, value, offset, size); + p4_out(reg, SH7751_PCIPDR); return 0; } -int pci_sh7751_init(struct pci_controller *hose) +static int sh7751_pci_probe(struct udevice *dev) { /* Double-check that we're a 7751 or 7751R chip */ if (p4_in(SH7751_PCICONF0) != PCI_SH7751_ID @@ -178,7 +210,23 @@ int pci_sh7751_init(struct pci_controller *hose) /* Finally, set central function init complete */ p4_out((SH7751_PCICR_PREFIX | SH7751_PCICR_CFIN), SH7751_PCICR); - pci_sh4_init(hose); - return 0; } + +static const struct dm_pci_ops sh7751_pci_ops = { + .read_config = sh7751_pci_read_config, + .write_config = sh7751_pci_write_config, +}; + +static const struct udevice_id sh7751_pci_ids[] = { + { .compatible = "renesas,pci-sh7751" }, + { } +}; + +U_BOOT_DRIVER(sh7751_pci) = { + .name = "sh7751_pci", + .id = UCLASS_PCI, + .of_match = sh7751_pci_ids, + .ops = &sh7751_pci_ops, + .probe = sh7751_pci_probe, +}; diff --git a/include/configs/exynos5-common.h b/include/configs/exynos5-common.h index 397bbf6d9d..e0a4d76d53 100644 --- a/include/configs/exynos5-common.h +++ b/include/configs/exynos5-common.h @@ -128,9 +128,9 @@ #define EXYNOS_IRAM_SECONDARY_BASE 0x02020018 #define BOOT_TARGET_DEVICES(func) \ + func(MMC, mmc, 2) \ func(MMC, mmc, 1) \ func(MMC, mmc, 0) \ - func(MMC, mmc, 2) \ func(PXE, pxe, na) \ func(DHCP, dhcp, na) diff --git a/include/configs/r2dplus.h b/include/configs/r2dplus.h index e10de1b920..0b16fb0f64 100644 --- a/include/configs/r2dplus.h +++ b/include/configs/r2dplus.h @@ -64,19 +64,6 @@ /* * SuperH PCI Bridge Configration */ -#define CONFIG_SH4_PCI #define CONFIG_SH7751_PCI -#define CONFIG_PCI_SCAN_SHOW 1 -#define __mem_pci - -#define CONFIG_PCI_MEM_BUS 0xFD000000 /* Memory space base addr */ -#define CONFIG_PCI_MEM_PHYS CONFIG_PCI_MEM_BUS -#define CONFIG_PCI_MEM_SIZE 0x01000000 /* Size of Memory window */ -#define CONFIG_PCI_IO_BUS 0xFE240000 /* IO space base address */ -#define CONFIG_PCI_IO_PHYS CONFIG_PCI_IO_BUS -#define CONFIG_PCI_IO_SIZE 0x00040000 /* Size of IO window */ -#define CONFIG_PCI_SYS_BUS CONFIG_SYS_SDRAM_BASE -#define CONFIG_PCI_SYS_PHYS CONFIG_SYS_SDRAM_BASE -#define CONFIG_PCI_SYS_SIZE CONFIG_SYS_SDRAM_SIZE #endif /* __CONFIG_H */ diff --git a/include/configs/rpi.h b/include/configs/rpi.h index 8473cecd94..77d2d5458a 100644 --- a/include/configs/rpi.h +++ b/include/configs/rpi.h @@ -55,6 +55,10 @@ #define CONFIG_SYS_MEMTEST_END 0x00200000 #define CONFIG_LOADADDR 0x00200000 +#ifdef CONFIG_ARM64 +#define CONFIG_SYS_BOOTM_LEN SZ_64M +#endif + /* Devices */ /* GPIO */ #define CONFIG_BCM2835_GPIO diff --git a/include/efi_api.h b/include/efi_api.h index 43778197af..cb895f31e5 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -483,7 +483,7 @@ struct efi_device_path_cdrom_path { struct efi_device_path dp; u32 boot_entry; u64 partition_start; - u64 partition_end; + u64 partition_size; } __packed; struct efi_device_path_file_path { @@ -1281,6 +1281,8 @@ struct efi_simple_network { struct efi_mac_address *dest_addr, u16 *protocol); struct efi_event *wait_for_packet; struct efi_simple_network_mode *mode; + /* private fields */ + u32 int_status; }; #define EFI_PXE_BASE_CODE_PROTOCOL_GUID \ diff --git a/include/efi_loader.h b/include/efi_loader.h index 5298ea7997..00eba8afa4 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -478,6 +478,10 @@ efi_status_t efi_get_memory_map(efi_uintn_t *memory_map_size, /* Adds a range into the EFI memory map */ efi_status_t efi_add_memory_map(uint64_t start, uint64_t pages, int memory_type, bool overlap_only_ram); +/* Adds a conventional range into the EFI memory map */ +efi_status_t efi_add_conventional_memory_map(u64 ram_start, u64 ram_end, + u64 ram_top); + /* Called by board init to initialize the EFI drivers */ efi_status_t efi_driver_init(void); /* Called by board init to initialize the EFI memory map */ 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/lib/efi_loader/efi_console.c b/lib/efi_loader/efi_console.c index d4765afb98..a55e4b33ec 100644 --- a/lib/efi_loader/efi_console.c +++ b/lib/efi_loader/efi_console.c @@ -156,13 +156,14 @@ static efi_status_t EFIAPI efi_cout_output_string( * Update the cursor position. * * The UEFI spec provides advance rules for U+0000, U+0008, U+000A, - * and U000D. All other characters, including control characters - * U+0007 (BEL) and U+0009 (TAB), have to increase the column by one. + * and U000D. All other control characters are ignored. Any non-control + * character increase the column by one. */ for (p = string; *p; ++p) { switch (*p) { case '\b': /* U+0008, backspace */ - con->cursor_column = max(0, con->cursor_column - 1); + if (con->cursor_column) + con->cursor_column--; break; case '\n': /* U+000A, newline */ con->cursor_column = 0; @@ -178,14 +179,21 @@ static efi_status_t EFIAPI efi_cout_output_string( */ break; default: - con->cursor_column++; + /* Exclude control codes */ + if (*p > 0x1f) + con->cursor_column++; break; } if (con->cursor_column >= mode->columns) { con->cursor_column = 0; con->cursor_row++; } - con->cursor_row = min(con->cursor_row, (s32)mode->rows - 1); + /* + * When we exceed the row count the terminal will scroll up one + * line. We have to adjust the cursor position. + */ + if (con->cursor_row >= mode->rows && con->cursor_row) + con->cursor_row--; } out: @@ -211,9 +219,9 @@ static bool cout_mode_matches(struct cout_mode *mode, int rows, int cols) /** * query_console_serial() - query console size * - * @rows pointer to return number of rows - * @columns pointer to return number of columns - * Returns 0 on success + * @rows: pointer to return number of rows + * @cols: pointer to return number of columns + * Returns: 0 on success */ static int query_console_serial(int *rows, int *cols) { @@ -371,6 +379,10 @@ static efi_status_t EFIAPI efi_cout_set_mode( if (mode_number >= efi_con_mode.max_mode) return EFI_EXIT(EFI_UNSUPPORTED); + + if (!efi_cout_modes[mode_number].present) + return EFI_EXIT(EFI_UNSUPPORTED); + efi_con_mode.mode = mode_number; EFI_CALL(efi_cout_clear_screen(this)); @@ -452,7 +464,7 @@ struct efi_simple_text_output_protocol efi_con_out = { * struct efi_cin_notify_function - registered console input notify function * * @link: link to list - * @data: key to notify + * @key: key to notify * @function: function to call */ struct efi_cin_notify_function { @@ -470,6 +482,7 @@ static LIST_HEAD(cin_notify_functions); * set_shift_mask() - set shift mask * * @mod: Xterm shift mask + * @key_state: receives the state of the shift, alt, control, and logo keys */ void set_shift_mask(int mod, struct efi_key_state *key_state) { @@ -492,7 +505,7 @@ void set_shift_mask(int mod, struct efi_key_state *key_state) * * This gets called when we have already parsed CSI. * - * @modifiers: bit mask (shift, alt, ctrl) + * @key_state: receives the state of the shift, alt, control, and logo keys * @return: the unmodified code */ static int analyze_modifiers(struct efi_key_state *key_state) diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c index eeeb806836..ea39f13b73 100644 --- a/lib/efi_loader/efi_device_path.c +++ b/lib/efi_loader/efi_device_path.c @@ -665,7 +665,7 @@ static void *dp_part_node(void *buf, struct blk_desc *desc, int part) cddp->dp.sub_type = DEVICE_PATH_SUB_TYPE_CDROM_PATH; cddp->dp.length = sizeof(*cddp); cddp->partition_start = info.start; - cddp->partition_end = info.size; + cddp->partition_size = info.size; buf = &cddp[1]; } else { diff --git a/lib/efi_loader/efi_device_path_to_text.c b/lib/efi_loader/efi_device_path_to_text.c index 96fd08971b..b20b7c097c 100644 --- a/lib/efi_loader/efi_device_path_to_text.c +++ b/lib/efi_loader/efi_device_path_to_text.c @@ -60,9 +60,18 @@ static char *dp_hardware(char *s, struct efi_device_path *dp) break; } case DEVICE_PATH_SUB_TYPE_VENDOR: { + int i, n; struct efi_device_path_vendor *vdp = (struct efi_device_path_vendor *)dp; - s += sprintf(s, "VenHw(%pUl)", &vdp->guid); + + s += sprintf(s, "VenHw(%pUl", &vdp->guid); + n = (int)vdp->dp.length - sizeof(struct efi_device_path_vendor); + if (n > 0) { + s += sprintf(s, ","); + for (i = 0; i < n; ++i) + s += sprintf(s, "%02x", vdp->vendor_data[i]); + } + s += sprintf(s, ")"); break; } default: @@ -115,17 +124,16 @@ static char *dp_msging(char *s, struct efi_device_path *dp) break; } case DEVICE_PATH_SUB_TYPE_MSG_MAC_ADDR: { + int i, n = sizeof(struct efi_mac_addr); struct efi_device_path_mac_addr *mdp = (struct efi_device_path_mac_addr *)dp; - if (mdp->if_type != 0 && mdp->if_type != 1) - break; - - s += sprintf(s, "MAC(%02x%02x%02x%02x%02x%02x,0x%1x)", - mdp->mac.addr[0], mdp->mac.addr[1], - mdp->mac.addr[2], mdp->mac.addr[3], - mdp->mac.addr[4], mdp->mac.addr[5], - mdp->if_type); + if (mdp->if_type <= 1) + n = 6; + s += sprintf(s, "MAC("); + for (i = 0; i < n; ++i) + s += sprintf(s, "%02x", mdp->mac.addr[i]); + s += sprintf(s, ",%u)", mdp->if_type); break; } @@ -133,7 +141,7 @@ static char *dp_msging(char *s, struct efi_device_path *dp) struct efi_device_path_usb_class *ucdp = (struct efi_device_path_usb_class *)dp; - s += sprintf(s, "USBClass(%x,%x,%x,%x,%x)", + s += sprintf(s, "UsbClass(0x%x,0x%x,0x%x,0x%x,0x%x)", ucdp->vendor_id, ucdp->product_id, ucdp->device_class, ucdp->device_subclass, ucdp->device_protocol); @@ -206,7 +214,8 @@ static char *dp_media(char *s, struct efi_device_path *dp) case DEVICE_PATH_SUB_TYPE_CDROM_PATH: { struct efi_device_path_cdrom_path *cddp = (struct efi_device_path_cdrom_path *)dp; - s += sprintf(s, "CDROM(0x%x)", cddp->boot_entry); + s += sprintf(s, "CDROM(%u,0x%llx,0x%llx)", cddp->boot_entry, + cddp->partition_start, cddp->partition_size); break; } case DEVICE_PATH_SUB_TYPE_FILE_PATH: { diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c index 7a6b06821a..9007a5f77f 100644 --- a/lib/efi_loader/efi_disk.c +++ b/lib/efi_loader/efi_disk.c @@ -41,11 +41,26 @@ struct efi_disk_obj { struct blk_desc *desc; }; +/** + * efi_disk_reset() - reset block device + * + * This function implements the Reset service of the EFI_BLOCK_IO_PROTOCOL. + * + * As U-Boot's block devices do not have a reset function simply return + * EFI_SUCCESS. + * + * See the Unified Extensible Firmware Interface (UEFI) specification for + * details. + * + * @this: pointer to the BLOCK_IO_PROTOCOL + * @extended_verification: extended verification + * Return: status code + */ static efi_status_t EFIAPI efi_disk_reset(struct efi_block_io *this, char extended_verification) { EFI_ENTRY("%p, %x", this, extended_verification); - return EFI_EXIT(EFI_DEVICE_ERROR); + return EFI_EXIT(EFI_SUCCESS); } enum efi_disk_direction { @@ -69,12 +84,12 @@ static efi_status_t efi_disk_rw_blocks(struct efi_block_io *this, blocks = buffer_size / blksz; lba += diskobj->offset; - debug("EFI: %s:%d blocks=%x lba=%llx blksz=%x dir=%d\n", __func__, - __LINE__, blocks, lba, blksz, direction); + EFI_PRINT("blocks=%x lba=%llx blksz=%x dir=%d\n", + blocks, lba, blksz, direction); /* We only support full block access */ if (buffer_size & (blksz - 1)) - return EFI_DEVICE_ERROR; + return EFI_BAD_BUFFER_SIZE; if (direction == EFI_DISK_READ) n = blk_dread(desc, lba, blocks, buffer); @@ -84,7 +99,7 @@ static efi_status_t efi_disk_rw_blocks(struct efi_block_io *this, /* We don't do interrupts, so check for timers cooperatively */ efi_timer_check(); - debug("EFI: %s:%d n=%lx blocks=%x\n", __func__, __LINE__, n, blocks); + EFI_PRINT("n=%lx blocks=%x\n", n, blocks); if (n != blocks) return EFI_DEVICE_ERROR; @@ -99,6 +114,20 @@ static efi_status_t EFIAPI efi_disk_read_blocks(struct efi_block_io *this, void *real_buffer = buffer; efi_status_t r; + if (!this) + return EFI_INVALID_PARAMETER; + /* TODO: check for media changes */ + if (media_id != this->media->media_id) + return EFI_MEDIA_CHANGED; + if (!this->media->media_present) + return EFI_NO_MEDIA; + /* media->io_align is a power of 2 */ + if ((uintptr_t)buffer & (this->media->io_align - 1)) + return EFI_INVALID_PARAMETER; + if (lba * this->media->block_size + buffer_size > + this->media->last_block * this->media->block_size) + return EFI_INVALID_PARAMETER; + #ifdef CONFIG_EFI_LOADER_BOUNCE_BUFFER if (buffer_size > EFI_LOADER_BOUNCE_BUFFER_SIZE) { r = efi_disk_read_blocks(this, media_id, lba, @@ -134,6 +163,22 @@ static efi_status_t EFIAPI efi_disk_write_blocks(struct efi_block_io *this, void *real_buffer = buffer; efi_status_t r; + if (!this) + return EFI_INVALID_PARAMETER; + if (this->media->read_only) + return EFI_WRITE_PROTECTED; + /* TODO: check for media changes */ + if (media_id != this->media->media_id) + return EFI_MEDIA_CHANGED; + if (!this->media->media_present) + return EFI_NO_MEDIA; + /* media->io_align is a power of 2 */ + if ((uintptr_t)buffer & (this->media->io_align - 1)) + return EFI_INVALID_PARAMETER; + if (lba * this->media->block_size + buffer_size > + this->media->last_block * this->media->block_size) + return EFI_INVALID_PARAMETER; + #ifdef CONFIG_EFI_LOADER_BOUNCE_BUFFER if (buffer_size > EFI_LOADER_BOUNCE_BUFFER_SIZE) { r = efi_disk_write_blocks(this, media_id, lba, @@ -288,6 +333,11 @@ static efi_status_t efi_disk_add_dev( /* Fill in EFI IO Media info (for read/write callbacks) */ diskobj->media.removable_media = desc->removable; diskobj->media.media_present = 1; + /* + * MediaID is just an arbitrary counter. + * We have to change it if the medium is removed or changed. + */ + diskobj->media.media_id = 1; diskobj->media.block_size = desc->blksz; diskobj->media.io_align = desc->blksz; diskobj->media.last_block = desc->lba - offset; diff --git a/lib/efi_loader/efi_gop.c b/lib/efi_loader/efi_gop.c index cad509bfea..1511e3bdb4 100644 --- a/lib/efi_loader/efi_gop.c +++ b/lib/efi_loader/efi_gop.c @@ -319,7 +319,7 @@ static efi_status_t gop_blt_vid_to_buf(struct efi_gop *this, * details. * * @this: the graphical output protocol - * @model_number: the mode to be set + * @mode_number: the mode to be set * Return: status code */ static efi_status_t EFIAPI gop_set_mode(struct efi_gop *this, u32 mode_number) diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c index b5775e0399..83cbc9154f 100644 --- a/lib/efi_loader/efi_memory.c +++ b/lib/efi_loader/efi_memory.c @@ -655,6 +655,54 @@ efi_status_t efi_get_memory_map(efi_uintn_t *memory_map_size, return EFI_SUCCESS; } +/** + * efi_add_conventional_memory_map() - add a RAM memory area to the map + * + * @ram_start: start address of a RAM memory area + * @ram_end: end address of a RAM memory area + * @ram_top: max address to be used as conventional memory + * Return: status code + */ +efi_status_t efi_add_conventional_memory_map(u64 ram_start, u64 ram_end, + u64 ram_top) +{ + u64 pages; + + /* Remove partial pages */ + ram_end &= ~EFI_PAGE_MASK; + ram_start = (ram_start + EFI_PAGE_MASK) & ~EFI_PAGE_MASK; + + if (ram_end <= ram_start) { + /* Invalid mapping */ + return EFI_INVALID_PARAMETER; + } + + pages = (ram_end - ram_start) >> EFI_PAGE_SHIFT; + + efi_add_memory_map(ram_start, pages, + EFI_CONVENTIONAL_MEMORY, false); + + /* + * Boards may indicate to the U-Boot memory core that they + * can not support memory above ram_top. Let's honor this + * in the efi_loader subsystem too by declaring any memory + * above ram_top as "already occupied by firmware". + */ + if (ram_top < ram_start) { + /* ram_top is before this region, reserve all */ + efi_add_memory_map(ram_start, pages, + EFI_BOOT_SERVICES_DATA, true); + } else if ((ram_top >= ram_start) && (ram_top < ram_end)) { + /* ram_top is inside this region, reserve parts */ + pages = (ram_end - ram_top) >> EFI_PAGE_SHIFT; + + efi_add_memory_map(ram_top, pages, + EFI_BOOT_SERVICES_DATA, true); + } + + return EFI_SUCCESS; +} + __weak void efi_add_known_memory(void) { u64 ram_top = board_get_usable_ram_top(0) & ~EFI_PAGE_MASK; @@ -672,42 +720,12 @@ __weak void efi_add_known_memory(void) /* Add RAM */ for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { - u64 ram_end, ram_start, pages; + u64 ram_end, ram_start; ram_start = (uintptr_t)map_sysmem(gd->bd->bi_dram[i].start, 0); ram_end = ram_start + gd->bd->bi_dram[i].size; - /* Remove partial pages */ - ram_end &= ~EFI_PAGE_MASK; - ram_start = (ram_start + EFI_PAGE_MASK) & ~EFI_PAGE_MASK; - - if (ram_end <= ram_start) { - /* Invalid mapping, keep going. */ - continue; - } - - pages = (ram_end - ram_start) >> EFI_PAGE_SHIFT; - - efi_add_memory_map(ram_start, pages, - EFI_CONVENTIONAL_MEMORY, false); - - /* - * Boards may indicate to the U-Boot memory core that they - * can not support memory above ram_top. Let's honor this - * in the efi_loader subsystem too by declaring any memory - * above ram_top as "already occupied by firmware". - */ - if (ram_top < ram_start) { - /* ram_top is before this region, reserve all */ - efi_add_memory_map(ram_start, pages, - EFI_BOOT_SERVICES_DATA, true); - } else if ((ram_top >= ram_start) && (ram_top < ram_end)) { - /* ram_top is inside this region, reserve parts */ - pages = (ram_end - ram_top) >> EFI_PAGE_SHIFT; - - efi_add_memory_map(ram_top, pages, - EFI_BOOT_SERVICES_DATA, true); - } + efi_add_conventional_memory_map(ram_start, ram_end, ram_top); } } diff --git a/lib/efi_loader/efi_net.c b/lib/efi_loader/efi_net.c index 825e064f9a..82d2595847 100644 --- a/lib/efi_loader/efi_net.c +++ b/lib/efi_loader/efi_net.c @@ -1,8 +1,18 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * EFI application network access support + * Simple network protocol + * PXE base code protocol * - * Copyright (c) 2016 Alexander Graf + * Copyright (c) 2016 Alexander Graf + * + * The simple network protocol has the following statuses and services + * to move between them: + * + * Start(): EfiSimpleNetworkStopped -> EfiSimpleNetworkStarted + * Initialize(): EfiSimpleNetworkStarted -> EfiSimpleNetworkInitialized + * Shutdown(): EfiSimpleNetworkInitialized -> EfiSimpleNetworkStarted + * Stop(): EfiSimpleNetworkStarted -> EfiSimpleNetworkStopped + * Reset(): EfiSimpleNetworkInitialized -> EfiSimpleNetworkInitialized */ #include <common.h> @@ -66,10 +76,13 @@ static efi_status_t EFIAPI efi_net_start(struct efi_simple_network *this) goto out; } - if (this->mode->state != EFI_NETWORK_STOPPED) + if (this->mode->state != EFI_NETWORK_STOPPED) { ret = EFI_ALREADY_STARTED; - else + } else { + this->int_status = 0; + wait_for_packet->is_signaled = false; this->mode->state = EFI_NETWORK_STARTED; + } out: return EFI_EXIT(ret); } @@ -96,10 +109,13 @@ static efi_status_t EFIAPI efi_net_stop(struct efi_simple_network *this) goto out; } - if (this->mode->state == EFI_NETWORK_STOPPED) + if (this->mode->state == EFI_NETWORK_STOPPED) { ret = EFI_NOT_STARTED; - else + } else { + /* Disable hardware and put it into the reset state */ + eth_halt(); this->mode->state = EFI_NETWORK_STOPPED; + } out: return EFI_EXIT(ret); } @@ -130,6 +146,15 @@ static efi_status_t EFIAPI efi_net_initialize(struct efi_simple_network *this, goto out; } + switch (this->mode->state) { + case EFI_NETWORK_INITIALIZED: + case EFI_NETWORK_STARTED: + break; + default: + r = EFI_NOT_STARTED; + goto out; + } + /* Setup packet buffers */ net_init(); /* Disable hardware and put it into the reset state */ @@ -144,6 +169,8 @@ static efi_status_t EFIAPI efi_net_initialize(struct efi_simple_network *this, r = EFI_DEVICE_ERROR; goto out; } else { + this->int_status = 0; + wait_for_packet->is_signaled = false; this->mode->state = EFI_NETWORK_INITIALIZED; } out: @@ -164,9 +191,31 @@ out: static efi_status_t EFIAPI efi_net_reset(struct efi_simple_network *this, int extended_verification) { + efi_status_t ret; + EFI_ENTRY("%p, %x", this, extended_verification); - return EFI_EXIT(EFI_CALL(efi_net_initialize(this, 0, 0))); + /* Check parameters */ + if (!this) { + ret = EFI_INVALID_PARAMETER; + goto out; + } + + switch (this->mode->state) { + case EFI_NETWORK_INITIALIZED: + break; + case EFI_NETWORK_STOPPED: + ret = EFI_NOT_STARTED; + goto out; + default: + ret = EFI_DEVICE_ERROR; + goto out; + } + + this->mode->state = EFI_NETWORK_STARTED; + ret = EFI_CALL(efi_net_initialize(this, 0, 0)); +out: + return EFI_EXIT(ret); } /* @@ -191,8 +240,21 @@ static efi_status_t EFIAPI efi_net_shutdown(struct efi_simple_network *this) goto out; } + switch (this->mode->state) { + case EFI_NETWORK_INITIALIZED: + break; + case EFI_NETWORK_STOPPED: + ret = EFI_NOT_STARTED; + goto out; + default: + ret = EFI_DEVICE_ERROR; + goto out; + } + eth_halt(); - this->mode->state = EFI_NETWORK_STOPPED; + this->int_status = 0; + wait_for_packet->is_signaled = false; + this->mode->state = EFI_NETWORK_STARTED; out: return EFI_EXIT(ret); @@ -270,7 +332,7 @@ static efi_status_t EFIAPI efi_net_statistics(struct efi_simple_network *this, /* * efi_net_mcastiptomac() - translate multicast IP address to MAC address * - * This function implements the Statistics service of the + * This function implements the MCastIPtoMAC service of the * EFI_SIMPLE_NETWORK_PROTOCOL. See the Unified Extensible Firmware Interface * (UEFI) specification for details. * @@ -285,9 +347,49 @@ static efi_status_t EFIAPI efi_net_mcastiptomac(struct efi_simple_network *this, struct efi_ip_address *ip, struct efi_mac_address *mac) { + efi_status_t ret = EFI_SUCCESS; + EFI_ENTRY("%p, %x, %p, %p", this, ipv6, ip, mac); - return EFI_EXIT(EFI_INVALID_PARAMETER); + if (!this || !ip || !mac) { + ret = EFI_INVALID_PARAMETER; + goto out; + } + + if (ipv6) { + ret = EFI_UNSUPPORTED; + goto out; + } + + /* Multi-cast addresses are in the range 224.0.0.0 - 239.255.255.255 */ + if ((ip->ip_addr[0] & 0xf0) != 0xe0) { + ret = EFI_INVALID_PARAMETER; + goto out; + }; + + switch (this->mode->state) { + case EFI_NETWORK_INITIALIZED: + case EFI_NETWORK_STARTED: + break; + default: + ret = EFI_NOT_STARTED; + goto out; + } + + memset(mac, 0, sizeof(struct efi_mac_address)); + + /* + * Copy lower 23 bits of IPv4 multi-cast address + * RFC 1112, RFC 7042 2.1.1. + */ + mac->mac_addr[0] = 0x01; + mac->mac_addr[1] = 0x00; + mac->mac_addr[2] = 0x5E; + mac->mac_addr[3] = ip->ip_addr[1] & 0x7F; + mac->mac_addr[4] = ip->ip_addr[2]; + mac->mac_addr[5] = ip->ip_addr[3]; +out: + return EFI_EXIT(ret); } /** @@ -297,7 +399,7 @@ static efi_status_t EFIAPI efi_net_mcastiptomac(struct efi_simple_network *this, * Protocol. See the UEFI spec for details. * * @this: the instance of the Simple Network Protocol - * @readwrite: true for read, false for write + * @read_write: true for read, false for write * @offset: offset in NVRAM * @buffer_size: size of buffer * @buffer: buffer @@ -350,10 +452,8 @@ static efi_status_t EFIAPI efi_net_get_status(struct efi_simple_network *this, } if (int_status) { - /* We send packets synchronously, so nothing is outstanding */ - *int_status = EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT; - if (new_rx_packet) - *int_status |= EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT; + *int_status = this->int_status; + this->int_status = 0; } if (txbuf) *txbuf = new_tx_packet; @@ -404,15 +504,33 @@ static efi_status_t EFIAPI efi_net_transmit goto out; } - if (header_size) { - /* - * TODO: We would need to create the header - * if header_size != 0 - */ - ret = EFI_UNSUPPORTED; + /* At least the IP header has to fit into the buffer */ + if (buffer_size < this->mode->media_header_size) { + ret = EFI_BUFFER_TOO_SMALL; goto out; } + /* + * TODO: + * Support VLANs. Use net_set_ether() for copying the header. Use a + * U_BOOT_ENV_CALLBACK to update the media header size. + */ + if (header_size) { + struct ethernet_hdr *header = buffer; + + if (!dest_addr || !protocol || + header_size != this->mode->media_header_size) { + ret = EFI_INVALID_PARAMETER; + goto out; + } + if (!src_addr) + src_addr = &this->mode->current_address; + + memcpy(header->et_dest, dest_addr, ARP_HLEN); + memcpy(header->et_src, src_addr, ARP_HLEN); + header->et_protlen = htons(*protocol); + } + switch (this->mode->state) { case EFI_NETWORK_STOPPED: ret = EFI_NOT_STARTED; @@ -429,7 +547,7 @@ static efi_status_t EFIAPI efi_net_transmit net_send_packet(transmit_buffer, buffer_size); new_tx_packet = buffer; - + this->int_status |= EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT; out: return EFI_EXIT(ret); } @@ -487,12 +605,6 @@ static efi_status_t EFIAPI efi_net_receive ret = EFI_NOT_READY; goto out; } - /* Check that we at least received an Ethernet header */ - if (net_rx_packet_len < sizeof(struct ethernet_hdr)) { - new_rx_packet = false; - ret = EFI_NOT_READY; - goto out; - } /* Fill export parameters */ eth_hdr = (struct ethernet_hdr *)net_rx_packet; protlen = ntohs(eth_hdr->et_protlen); @@ -517,7 +629,8 @@ static efi_status_t EFIAPI efi_net_receive /* Copy packet */ memcpy(buffer, net_rx_packet, net_rx_packet_len); *buffer_size = net_rx_packet_len; - new_rx_packet = false; + new_rx_packet = 0; + this->int_status &= ~EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT; out: return EFI_EXIT(ret); } @@ -526,6 +639,9 @@ out: * efi_net_set_dhcp_ack() - take note of a selected DHCP IP address * * This function is called by dhcp_handler(). + * + * @pkt: packet received by dhcp_handler() + * @len: length of the packet received */ void efi_net_set_dhcp_ack(void *pkt, int len) { @@ -548,7 +664,6 @@ void efi_net_set_dhcp_ack(void *pkt, int len) static void efi_net_push(void *pkt, int len) { new_rx_packet = true; - wait_for_packet->is_signaled = true; } /** @@ -556,8 +671,8 @@ static void efi_net_push(void *pkt, int len) * * This notification function is called in every timer cycle. * - * @event the event for which this notification function is registered - * @context event context - not used in this function + * @event: the event for which this notification function is registered + * @context: event context - not used in this function */ static void EFIAPI efi_network_timer_notify(struct efi_event *event, void *context) @@ -577,6 +692,17 @@ static void EFIAPI efi_network_timer_notify(struct efi_event *event, push_packet = efi_net_push; eth_rx(); push_packet = NULL; + if (new_rx_packet) { + /* Check that we at least received an Ethernet header */ + if (net_rx_packet_len >= + sizeof(struct ethernet_hdr)) { + this->int_status |= + EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT; + wait_for_packet->is_signaled = true; + } else { + new_rx_packet = 0; + } + } } out: EFI_EXIT(EFI_SUCCESS); @@ -751,9 +877,10 @@ efi_status_t efi_net_register(void) netobj->net.transmit = efi_net_transmit; netobj->net.receive = efi_net_receive; netobj->net.mode = &netobj->net_mode; - netobj->net_mode.state = EFI_NETWORK_STARTED; + netobj->net_mode.state = EFI_NETWORK_STOPPED; memcpy(netobj->net_mode.current_address.mac_addr, eth_get_ethaddr(), 6); netobj->net_mode.hwaddr_size = ARP_HLEN; + netobj->net_mode.media_header_size = ETHER_HDR_SIZE; netobj->net_mode.max_packet_size = PKTSIZE; netobj->net_mode.if_type = ARP_ETHER; diff --git a/lib/efi_selftest/efi_selftest_snp.c b/lib/efi_selftest/efi_selftest_snp.c index 4c26619001..9797ecaf42 100644 --- a/lib/efi_selftest/efi_selftest_snp.c +++ b/lib/efi_selftest/efi_selftest_snp.c @@ -228,6 +228,26 @@ static int setup(const efi_handle_t handle, efi_st_error("WaitForPacket event missing\n"); return EFI_ST_FAILURE; } + if (net->mode->state == EFI_NETWORK_INITIALIZED) { + /* + * Shut down network adapter. + */ + ret = net->shutdown(net); + if (ret != EFI_SUCCESS) { + efi_st_error("Failed to shut down network adapter\n"); + return EFI_ST_FAILURE; + } + } + if (net->mode->state == EFI_NETWORK_STARTED) { + /* + * Stop network adapter. + */ + ret = net->stop(net); + if (ret != EFI_SUCCESS) { + efi_st_error("Failed to stop network adapter\n"); + return EFI_ST_FAILURE; + } + } /* * Start network adapter. */ @@ -236,6 +256,10 @@ static int setup(const efi_handle_t handle, efi_st_error("Failed to start network adapter\n"); return EFI_ST_FAILURE; } + if (net->mode->state != EFI_NETWORK_STARTED) { + efi_st_error("Failed to start network adapter\n"); + return EFI_ST_FAILURE; + } /* * Initialize network adapter. */ @@ -244,6 +268,10 @@ static int setup(const efi_handle_t handle, efi_st_error("Failed to initialize network adapter\n"); return EFI_ST_FAILURE; } + if (net->mode->state != EFI_NETWORK_INITIALIZED) { + efi_st_error("Failed to initialize network adapter\n"); + return EFI_ST_FAILURE; + } return EFI_ST_SUCCESS; } @@ -268,6 +296,7 @@ static int execute(void) struct efi_mac_address destaddr; size_t buffer_size; u8 *addr; + /* * The timeout is to occur after 10 s. */ @@ -298,6 +327,8 @@ static int execute(void) events[0] = timer; events[1] = net->wait_for_packet; for (;;) { + u32 int_status; + /* * Wait for packet to be received or timer event. */ @@ -323,8 +354,17 @@ static int execute(void) * Receive packet */ buffer_size = sizeof(buffer); - net->receive(net, NULL, &buffer_size, &buffer, - &srcaddr, &destaddr, NULL); + ret = net->get_status(net, &int_status, NULL); + if (ret != EFI_SUCCESS) { + efi_st_error("Failed to get status"); + return EFI_ST_FAILURE; + } + if (!(int_status & EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT)) { + efi_st_error("RX interrupt not set"); + return EFI_ST_FAILURE; + } + ret = net->receive(net, NULL, &buffer_size, &buffer, + &srcaddr, &destaddr, NULL); if (ret != EFI_SUCCESS) { efi_st_error("Failed to receive packet"); return EFI_ST_FAILURE; @@ -400,21 +440,29 @@ static int teardown(void) } if (net) { /* - * Stop network adapter. + * Shut down network adapter. */ - ret = net->stop(net); + ret = net->shutdown(net); if (ret != EFI_SUCCESS) { - efi_st_error("Failed to stop network adapter\n"); + efi_st_error("Failed to shut down network adapter\n"); exit_status = EFI_ST_FAILURE; } + if (net->mode->state != EFI_NETWORK_STARTED) { + efi_st_error("Failed to shutdown network adapter\n"); + return EFI_ST_FAILURE; + } /* - * Shut down network adapter. + * Stop network adapter. */ - ret = net->shutdown(net); + ret = net->stop(net); if (ret != EFI_SUCCESS) { - efi_st_error("Failed to shut down network adapter\n"); + efi_st_error("Failed to stop network adapter\n"); exit_status = EFI_ST_FAILURE; } + if (net->mode->state != EFI_NETWORK_STOPPED) { + efi_st_error("Failed to stop network adapter\n"); + return EFI_ST_FAILURE; + } } return exit_status; 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); } @@ -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); @@ -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; @@ -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; +} |