From e87527b57dfb1472a62059c0ff6a96dee01729d8 Mon Sep 17 00:00:00 2001 From: Mauri Sandberg Date: Mon, 22 Mar 2021 16:36:58 +0200 Subject: [PATCH 01/31] ath79: copy cfi patch from 5.4 over to 5.10 Add the same patch to 5.10 too. The patch is in process of being upstreamed. Fixes: 8cc0fa8facea ("ath79: cfi: cmdset_0002: amd chip 0x2201 - write words") Signed-off-by: Mauri Sandberg [add Fixes:] Signed-off-by: Adrian Schmutzler --- ...set_0002-AMD-chip-0x2201-write-words.patch | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 target/linux/ath79/patches-5.10/471-mtd-cfi_cmdset_0002-AMD-chip-0x2201-write-words.patch diff --git a/target/linux/ath79/patches-5.10/471-mtd-cfi_cmdset_0002-AMD-chip-0x2201-write-words.patch b/target/linux/ath79/patches-5.10/471-mtd-cfi_cmdset_0002-AMD-chip-0x2201-write-words.patch new file mode 100644 index 0000000000..3c80872ef4 --- /dev/null +++ b/target/linux/ath79/patches-5.10/471-mtd-cfi_cmdset_0002-AMD-chip-0x2201-write-words.patch @@ -0,0 +1,58 @@ +From f1f811410af297c848e9ec17eaa280d190fdce10 Mon Sep 17 00:00:00 2001 +From: Mauri Sandberg +Date: Tue, 23 Feb 2021 18:09:31 +0200 +Subject: [PATCH] mtd: cfi_cmdset_0002: AMD chip 0x2201 - write words + +Buffer writes do not work with AMD chip 0x2201. The chip in question +is a AMD/Spansion/Cypress Semiconductor S29GL256N and datasheet [1] +talks about writing buffers being possible. While waiting for a neater +solution resort to writing word-sized chunks only. + +Without the patch kernel logs will be flooded with entries like below: + +jffs2_scan_eraseblock(): End of filesystem marker found at 0x0 +jffs2_build_filesystem(): unlocking the mtd device... +done. +jffs2_build_filesystem(): erasing all blocks after the end marker... +MTD do_write_buffer_wait(): software timeout, address:0x01ec000a. +jffs2: Write clean marker to block at 0x01920000 failed: -5 +MTD do_write_buffer_wait(): software timeout, address:0x01e2000a. +jffs2: Write clean marker to block at 0x01880000 failed: -5 +MTD do_write_buffer_wait(): software timeout, address:0x01e0000a. +jffs2: Write clean marker to block at 0x01860000 failed: -5 +MTD do_write_buffer_wait(): software timeout, address:0x01dc000a. +jffs2: Write clean marker to block at 0x01820000 failed: -5 +MTD do_write_buffer_wait(): software timeout, address:0x01da000a. +jffs2: Write clean marker to block at 0x01800000 failed: -5 +... + +Tested on a Buffalo wzr-hp-g300nh running kernel 5.10.16. + +[1] https://www.cypress.com/file/219941/download +or https://datasheetspdf.com/pdf-file/565708/SPANSION/S29GL256N/1 + +Signed-off-by: Mauri Sandberg +--- + drivers/mtd/chips/cfi_cmdset_0002.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c +index a1f3e1031c3d..28b6f3583f8a 100644 +--- a/drivers/mtd/chips/cfi_cmdset_0002.c ++++ b/drivers/mtd/chips/cfi_cmdset_0002.c +@@ -272,6 +272,10 @@ static void fixup_use_write_buffers(struct mtd_info *mtd) + { + struct map_info *map = mtd->priv; + struct cfi_private *cfi = map->fldrv_priv; ++ ++ if ((cfi->mfr == CFI_MFR_AMD) && (cfi->id == 0x2201)) ++ return; ++ + if (cfi->cfiq->BufWriteTimeoutTyp) { + pr_debug("Using buffer write method\n"); + mtd->_write = cfi_amdstd_write_buffers; + +base-commit: 5de15b610f785f0e188fefb707f0b19de156968a +-- +2.25.1 + From bf7ddb18f1bfa0b61b4dc43732c114f20900bd4b Mon Sep 17 00:00:00 2001 From: Shiji Yang Date: Sun, 21 Mar 2021 22:43:59 +0800 Subject: [PATCH 02/31] ramips: speed up spi frequency for Youku YK-L1 Youku YK-L1 has a huge storage space up to 32 MB. It is better to use a higher spi clock to read or write serial nor flash chips. Youku YK-L1 has Winbond w25q256fvfg on board that can support 104 MHz spi clock so 48 MHz is safe enough. The real frequency can only be sysclk(580MHz ) /3 /(2^n) so 80 MHz defined in dts file will set only 48 MHz in spi bus. Signed-off-by: Shiji Yang --- target/linux/ramips/dts/mt7620a_youku_yk1.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/linux/ramips/dts/mt7620a_youku_yk1.dts b/target/linux/ramips/dts/mt7620a_youku_yk1.dts index 8727b011d4..3b84b07b8b 100644 --- a/target/linux/ramips/dts/mt7620a_youku_yk1.dts +++ b/target/linux/ramips/dts/mt7620a_youku_yk1.dts @@ -69,7 +69,7 @@ flash@0 { compatible = "jedec,spi-nor"; reg = <0>; - spi-max-frequency = <25000000>; + spi-max-frequency = <80000000>; m25p,fast-read; partitions { From 851dadc257b7223f879a3733507e83cfcaae1af1 Mon Sep 17 00:00:00 2001 From: Adrian Schmutzler Date: Mon, 22 Mar 2021 20:58:16 +0100 Subject: [PATCH 03/31] realtek: add ZYXEL_VERS to DEVICE_VARS Otherwise, the last defined value will be set for all devices. Fixes: c6c8d597e183 ("realtek: Add generic zyxel_gs1900 image definition") Signed-off-by: Adrian Schmutzler --- target/linux/realtek/image/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/target/linux/realtek/image/Makefile b/target/linux/realtek/image/Makefile index d867d2a3d9..18e5fedb9b 100644 --- a/target/linux/realtek/image/Makefile +++ b/target/linux/realtek/image/Makefile @@ -6,6 +6,8 @@ include $(INCLUDE_DIR)/image.mk KERNEL_LOADADDR = 0x80000000 KERNEL_ENTRY = 0x80000400 +DEVICE_VARS += ZYXEL_VERS + define Build/zyxel-vers ( echo VERS;\ for hw in $(1); do\ From 7f04d675170d255580edf77d4ff7c0adebb57609 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Tue, 23 Mar 2021 20:12:22 +0100 Subject: [PATCH 04/31] bmips: add experimental PCI/PCIe support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These PCI drivers are a bit hacky and definitely not suitable for upstreaming, but hopefully we can use them as a base for developing proper upstream PCI drivers. Signed-off-by: Álvaro Fernández Rojas --- target/linux/bmips/config-5.10 | 28 + .../bmips/dts/bcm6318-comtrend-ar-5315u.dts | 4 + target/linux/bmips/dts/bcm6318.dtsi | 35 + target/linux/bmips/dts/bcm63268.dtsi | 39 + .../bmips/dts/bcm6328-comtrend-ar-5387un.dts | 4 + target/linux/bmips/dts/bcm6328.dtsi | 39 + .../bmips/dts/bcm6358-huawei-hg556a-b.dts | 4 + target/linux/bmips/dts/bcm6358.dtsi | 25 + .../bmips/dts/bcm6362-netgear-dgnd3700-v2.dts | 4 + target/linux/bmips/dts/bcm6362.dtsi | 37 + .../bmips/dts/bcm6368-comtrend-vr-3025u.dts | 4 + target/linux/bmips/dts/bcm6368.dtsi | 28 + .../bmips/files/arch/mips/pci/fixup-bmips.c | 18 + .../drivers/pci/controller/pci-bcm6348.c | 825 ++++++++++++++++++ .../drivers/pci/controller/pcie-bcm6318.c | 402 +++++++++ .../drivers/pci/controller/pcie-bcm6328.c | 412 +++++++++ .../600-mips-bmips-add-pci-support.patch | 20 + ...controllers-add-bcm6328-pcie-support.patch | 22 + ...controllers-add-bcm6318-pcie-support.patch | 22 + ...-controllers-add-bcm6348-pci-support.patch | 22 + 20 files changed, 1994 insertions(+) create mode 100644 target/linux/bmips/files/arch/mips/pci/fixup-bmips.c create mode 100644 target/linux/bmips/files/drivers/pci/controller/pci-bcm6348.c create mode 100644 target/linux/bmips/files/drivers/pci/controller/pcie-bcm6318.c create mode 100644 target/linux/bmips/files/drivers/pci/controller/pcie-bcm6328.c create mode 100644 target/linux/bmips/patches-5.10/600-mips-bmips-add-pci-support.patch create mode 100644 target/linux/bmips/patches-5.10/601-pci-controllers-add-bcm6328-pcie-support.patch create mode 100644 target/linux/bmips/patches-5.10/602-pci-controllers-add-bcm6318-pcie-support.patch create mode 100644 target/linux/bmips/patches-5.10/603-pci-controllers-add-bcm6348-pci-support.patch diff --git a/target/linux/bmips/config-5.10 b/target/linux/bmips/config-5.10 index e2fc405c57..253b528ffd 100644 --- a/target/linux/bmips/config-5.10 +++ b/target/linux/bmips/config-5.10 @@ -16,6 +16,17 @@ CONFIG_BCM63XX_POWER=y CONFIG_BCM7038_L1_IRQ=y CONFIG_BCM7038_WDT=y CONFIG_BCM7120_L2_IRQ=y +CONFIG_BCMA=y +CONFIG_BCMA_BLOCKIO=y +# CONFIG_BCMA_DEBUG is not set +# CONFIG_BCMA_DRIVER_GMAC_CMN is not set +# CONFIG_BCMA_DRIVER_MIPS is not set +CONFIG_BCMA_DRIVER_PCI=y +# CONFIG_BCMA_DRIVER_PCI_HOSTMODE is not set +CONFIG_BCMA_HOST_PCI=y +CONFIG_BCMA_HOST_PCI_POSSIBLE=y +# CONFIG_BCMA_HOST_SOC is not set +CONFIG_BLK_MQ_PCI=y CONFIG_BLK_PM=y CONFIG_BMIPS_GENERIC=y CONFIG_BOARD_SCACHE=y @@ -139,6 +150,7 @@ CONFIG_MDIO_BUS=y CONFIG_MDIO_BUS_MUX=y CONFIG_MDIO_BUS_MUX_BCM6368=y CONFIG_MDIO_DEVICE=y +CONFIG_MDIO_DEVRES=y CONFIG_MEMFD_CREATE=y CONFIG_MFD_SYSCON=y CONFIG_MIGRATION=y @@ -194,6 +206,13 @@ CONFIG_OF_KOBJ=y CONFIG_OF_MDIO=y CONFIG_OF_NET=y CONFIG_PADATA=y +CONFIG_PCI=y +CONFIG_PCIEPORTBUS=y +CONFIG_PCIE_BCM6318=y +CONFIG_PCIE_BCM6328=y +CONFIG_PCIE_PME=y +CONFIG_PCI_BCM6348=y +CONFIG_PCI_DOMAINS=y CONFIG_PCI_DRIVERS_LEGACY=y CONFIG_PERF_USE_VMALLOC=y CONFIG_PGTABLE_LEVELS=2 @@ -244,6 +263,15 @@ CONFIG_SPI_BCM63XX_HSSPI=y CONFIG_SPI_MASTER=y CONFIG_SPI_MEM=y CONFIG_SRCU=y +CONFIG_SSB=y +CONFIG_SSB_B43_PCI_BRIDGE=y +CONFIG_SSB_BLOCKIO=y +# CONFIG_SSB_DRIVER_MIPS is not set +CONFIG_SSB_DRIVER_PCICORE=y +CONFIG_SSB_DRIVER_PCICORE_POSSIBLE=y +CONFIG_SSB_PCIHOST=y +CONFIG_SSB_PCIHOST_POSSIBLE=y +CONFIG_SSB_SPROM=y CONFIG_SWAP_IO_SPACE=y CONFIG_SWPHY=y CONFIG_SYNC_R4K=y diff --git a/target/linux/bmips/dts/bcm6318-comtrend-ar-5315u.dts b/target/linux/bmips/dts/bcm6318-comtrend-ar-5315u.dts index a5ae435a3a..5b44b05e70 100644 --- a/target/linux/bmips/dts/bcm6318-comtrend-ar-5315u.dts +++ b/target/linux/bmips/dts/bcm6318-comtrend-ar-5315u.dts @@ -164,6 +164,10 @@ status = "okay"; }; +&pcie { + status = "okay"; +}; + &pinctrl { pinctrl_leds: leds { function = "led"; diff --git a/target/linux/bmips/dts/bcm6318.dtsi b/target/linux/bmips/dts/bcm6318.dtsi index e7dc38e937..9067db952e 100644 --- a/target/linux/bmips/dts/bcm6318.dtsi +++ b/target/linux/bmips/dts/bcm6318.dtsi @@ -347,6 +347,41 @@ status = "disabled"; }; + pcie: pcie@10010000 { + compatible = "brcm,bcm6318-pcie"; + reg = <0x10010000 0x10000>; + #address-cells = <3>; + #size-cells = <2>; + + device_type = "pci"; + bus-range = <0x00 0x01>; + ranges = <0x2000000 0 0x10200000 0x10200000 0 0x100000>; + linux,pci-probe-only = <1>; + + interrupt-parent = <&periph_intc>; + interrupts = ; + + clocks = <&periph_clk BCM6318_CLK_PCIE>, + <&periph_clk BCM6318_CLK_PCIE25>, + <&ubus_clk BCM6318_UCLK_PCIE>; + clock-names = "pcie", + "pcie25", + "pcie-ubus"; + + resets = <&periph_rst BCM6318_RST_PCIE>, + <&periph_rst BCM6318_RST_PCIE_EXT>, + <&periph_rst BCM6318_RST_PCIE_CORE>, + <&periph_rst BCM6318_RST_PCIE_HARD>; + reset-names = "pcie", + "pcie-ext", + "pcie-core", + "pcie-hard"; + + power-domains = <&periph_pwr BCM6318_POWER_DOMAIN_PCIE>; + + status = "disabled"; + }; + switch0: switch@10080000 { #address-cells = <1>; #size-cells = <0>; diff --git a/target/linux/bmips/dts/bcm63268.dtsi b/target/linux/bmips/dts/bcm63268.dtsi index 284d2c8ef0..32cbbd7200 100644 --- a/target/linux/bmips/dts/bcm63268.dtsi +++ b/target/linux/bmips/dts/bcm63268.dtsi @@ -371,6 +371,12 @@ status = "disabled"; }; + serdes_cntl: syscon@10001804 { + compatible = "syscon"; + reg = <0x10001804 0x4>; + native-endian; + }; + periph_pwr: power-controller@1000184c { compatible = "brcm,bcm63268-power-controller"; reg = <0x1000184c 0x4>; @@ -468,6 +474,39 @@ status = "disabled"; }; + pcie: pcie@106e0000 { + compatible = "brcm,bcm6328-pcie"; + reg = <0x106e0000 0x10000>; + #address-cells = <3>; + #size-cells = <2>; + + device_type = "pci"; + bus-range = <0x00 0x01>; + ranges = <0x2000000 0 0x11000000 0x11000000 0 0xf00000>; + linux,pci-probe-only = <1>; + + interrupt-parent = <&periph_intc>; + interrupts = ; + + clocks = <&periph_clk BCM63268_CLK_PCIE>; + clock-names = "pcie"; + + resets = <&periph_rst BCM63268_RST_PCIE>, + <&periph_rst BCM63268_RST_PCIE_EXT>, + <&periph_rst BCM63268_RST_PCIE_CORE>, + <&periph_rst BCM63268_RST_PCIE_HARD>; + reset-names = "pcie", + "pcie-ext", + "pcie-core", + "pcie-hard"; + + power-domains = <&periph_pwr BCM63268_POWER_DOMAIN_PCIE>; + + brcm,serdes = <&serdes_cntl>; + + status = "disabled"; + }; + switch0: switch@10700000 { #address-cells = <1>; #size-cells = <0>; diff --git a/target/linux/bmips/dts/bcm6328-comtrend-ar-5387un.dts b/target/linux/bmips/dts/bcm6328-comtrend-ar-5387un.dts index 9ebd6c5c4d..261162454f 100644 --- a/target/linux/bmips/dts/bcm6328-comtrend-ar-5387un.dts +++ b/target/linux/bmips/dts/bcm6328-comtrend-ar-5387un.dts @@ -111,6 +111,10 @@ status = "okay"; }; +&pcie { + status = "okay"; +}; + &pinctrl { pinctrl_leds: leds { function = "led"; diff --git a/target/linux/bmips/dts/bcm6328.dtsi b/target/linux/bmips/dts/bcm6328.dtsi index 64fd04142c..76d7a257d4 100644 --- a/target/linux/bmips/dts/bcm6328.dtsi +++ b/target/linux/bmips/dts/bcm6328.dtsi @@ -317,6 +317,12 @@ status = "disabled"; }; + serdes_cntl: syscon@10001800 { + compatible = "syscon"; + reg = <0x10001800 0x4>; + native-endian; + }; + periph_pwr: power-controller@10001848 { compatible = "brcm,bcm6328-power-controller"; reg = <0x10001848 0x4>; @@ -462,5 +468,38 @@ reg = <1>; }; }; + + pcie: pcie@10e40000 { + compatible = "brcm,bcm6328-pcie"; + reg = <0x10e40000 0x10000>; + #address-cells = <3>; + #size-cells = <2>; + + device_type = "pci"; + bus-range = <0x00 0x01>; + ranges = <0x2000000 0 0x10f00000 0x10f00000 0 0x100000>; + linux,pci-probe-only = <1>; + + interrupt-parent = <&periph_intc>; + interrupts = ; + + clocks = <&periph_clk BCM6328_CLK_PCIE>; + clock-names = "pcie"; + + resets = <&periph_rst BCM6328_RST_PCIE>, + <&periph_rst BCM6328_RST_PCIE_EXT>, + <&periph_rst BCM6328_RST_PCIE_CORE>, + <&periph_rst BCM6328_RST_PCIE_HARD>; + reset-names = "pcie", + "pcie-ext", + "pcie-core", + "pcie-hard"; + + power-domains = <&periph_pwr BCM6328_POWER_DOMAIN_PCIE>; + + brcm,serdes = <&serdes_cntl>; + + status = "disabled"; + }; }; }; diff --git a/target/linux/bmips/dts/bcm6358-huawei-hg556a-b.dts b/target/linux/bmips/dts/bcm6358-huawei-hg556a-b.dts index ba776caf78..0f21ca4a6b 100644 --- a/target/linux/bmips/dts/bcm6358-huawei-hg556a-b.dts +++ b/target/linux/bmips/dts/bcm6358-huawei-hg556a-b.dts @@ -129,6 +129,10 @@ status = "okay"; }; +&pci { + status = "okay"; +}; + &pflash { status = "okay"; diff --git a/target/linux/bmips/dts/bcm6358.dtsi b/target/linux/bmips/dts/bcm6358.dtsi index c06001c62d..fee9850059 100644 --- a/target/linux/bmips/dts/bcm6358.dtsi +++ b/target/linux/bmips/dts/bcm6358.dtsi @@ -280,6 +280,31 @@ status = "disabled"; }; + pci: pci@fffe1000 { + compatible = "brcm,bcm6348-pci"; + reg = <0xfffe1000 0x200>, + <0x08000000 0x10000>; + reg-names = "pci", + "pci-io"; + #address-cells = <3>; + #size-cells = <2>; + + device_type = "pci"; + bus-range = <0x00 0x01>; + ranges = <0x2000000 0 0x30000000 0x30000000 0 0x8000000>; + linux,pci-probe-only = <1>; + + interrupt-parent = <&periph_intc>; + interrupts = ; + + resets = <&periph_rst BCM6358_RST_MPI>; + reset-names = "pci"; + + brcm,remap; + + status = "disabled"; + }; + ehci: usb@fffe1300 { compatible = "brcm,bcm6358-ehci", "generic-ehci"; reg = <0xfffe1300 0x100>; diff --git a/target/linux/bmips/dts/bcm6362-netgear-dgnd3700-v2.dts b/target/linux/bmips/dts/bcm6362-netgear-dgnd3700-v2.dts index 0d88169184..3ad37fed71 100644 --- a/target/linux/bmips/dts/bcm6362-netgear-dgnd3700-v2.dts +++ b/target/linux/bmips/dts/bcm6362-netgear-dgnd3700-v2.dts @@ -209,6 +209,10 @@ status = "okay"; }; +&pcie { + status = "okay"; +}; + &pinctrl { pinctrl_leds: leds { function = "led"; diff --git a/target/linux/bmips/dts/bcm6362.dtsi b/target/linux/bmips/dts/bcm6362.dtsi index 9a3d9c1f66..1ae1522287 100644 --- a/target/linux/bmips/dts/bcm6362.dtsi +++ b/target/linux/bmips/dts/bcm6362.dtsi @@ -406,6 +406,12 @@ status = "disabled"; }; + serdes_cntl: syscon@10001804 { + compatible = "syscon"; + reg = <0x10001804 0x4>; + native-endian; + }; + periph_pwr: power-controller@10001848 { compatible = "brcm,bcm6362-power-controller"; reg = <0x10001848 0x4>; @@ -559,5 +565,36 @@ reg = <1>; }; }; + + pcie: pcie@10e40000 { + compatible = "brcm,bcm6328-pcie"; + reg = <0x10e40000 0x10000>; + #address-cells = <3>; + #size-cells = <2>; + + device_type = "pci"; + bus-range = <0x00 0x01>; + ranges = <0x2000000 0 0x10f00000 0x10f00000 0 0x100000>; + linux,pci-probe-only = <1>; + + interrupt-parent = <&periph_intc>; + interrupts = ; + + clocks = <&periph_clk BCM6362_CLK_PCIE>; + clock-names = "pcie"; + + resets = <&periph_rst BCM6362_RST_PCIE>, + <&periph_rst BCM6362_RST_PCIE_EXT>, + <&periph_rst BCM6362_RST_PCIE_CORE>; + reset-names = "pcie", + "pcie-ext", + "pcie-core"; + + power-domains = <&periph_pwr BCM6362_POWER_DOMAIN_PCIE>; + + brcm,serdes = <&serdes_cntl>; + + status = "disabled"; + }; }; }; diff --git a/target/linux/bmips/dts/bcm6368-comtrend-vr-3025u.dts b/target/linux/bmips/dts/bcm6368-comtrend-vr-3025u.dts index b597a05f3a..c036b1cbec 100644 --- a/target/linux/bmips/dts/bcm6368-comtrend-vr-3025u.dts +++ b/target/linux/bmips/dts/bcm6368-comtrend-vr-3025u.dts @@ -69,6 +69,10 @@ status = "okay"; }; +&pci { + status = "okay"; +}; + &pflash { status = "okay"; diff --git a/target/linux/bmips/dts/bcm6368.dtsi b/target/linux/bmips/dts/bcm6368.dtsi index 5b5064b29e..9f59182517 100644 --- a/target/linux/bmips/dts/bcm6368.dtsi +++ b/target/linux/bmips/dts/bcm6368.dtsi @@ -414,6 +414,34 @@ status = "disabled"; }; + pci: pci@10001000 { + compatible = "brcm,bcm6348-pci"; + reg = <0x10001000 0x200>, + <0x08000000 0x10000>; + reg-names = "pci", + "pci-io"; + #address-cells = <3>; + #size-cells = <2>; + + device_type = "pci"; + bus-range = <0x00 0x01>; + ranges = <0x2000000 0 0x30000000 0x30000000 0 0x8000000>; + linux,pci-probe-only = <1>; + + interrupt-parent = <&periph_intc>; + interrupts = ; + + resets = <&periph_rst BCM6368_RST_MPI>; + reset-names = "pci"; + + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pci>; + + brcm,remap; + + status = "disabled"; + }; + ehci: usb@10001500 { compatible = "brcm,bcm6368-ehci", "generic-ehci"; reg = <0x10001500 0x100>; diff --git a/target/linux/bmips/files/arch/mips/pci/fixup-bmips.c b/target/linux/bmips/files/arch/mips/pci/fixup-bmips.c new file mode 100644 index 0000000000..34050407c4 --- /dev/null +++ b/target/linux/bmips/files/arch/mips/pci/fixup-bmips.c @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2020 Álvaro Fernández Rojas + */ + +#include + +int bmips_pci_irq = -1; + +int pcibios_plat_dev_init(struct pci_dev *pci_dev) +{ + return PCIBIOS_SUCCESSFUL; +} + +int pcibios_map_irq(const struct pci_dev *pci_dev, u8 slot, u8 pin) +{ + return bmips_pci_irq; +} diff --git a/target/linux/bmips/files/drivers/pci/controller/pci-bcm6348.c b/target/linux/bmips/files/drivers/pci/controller/pci-bcm6348.c new file mode 100644 index 0000000000..c1d3bde5df --- /dev/null +++ b/target/linux/bmips/files/drivers/pci/controller/pci-bcm6348.c @@ -0,0 +1,825 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * BCM6348 PCI Controller Driver + * + * Copyright (C) 2020 Álvaro Fernández Rojas + * Copyright (C) 2015 Jonas Gorski + * Copyright (C) 2008 Maxime Bizon + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../pci.h" + +#define CARDBUS_DUMMY_ID 0x6348 +#define CARDBUS_PCI_IDSEL 0x8 +#define FAKE_CB_BRIDGE_SLOT 0x1e + +#define BCMPCI_REG_TIMERS 0x40 +#define REG_TIMER_TRDY_SHIFT 0 +#define REG_TIMER_TRDY_MASK (0xff << REG_TIMER_TRDY_SHIFT) +#define REG_TIMER_RETRY_SHIFT 8 +#define REG_TIMER_RETRY_MASK (0xff << REG_TIMER_RETRY_SHIFT) + +#define MPI_SP0_RANGE_REG 0x100 +#define MPI_SP0_REMAP_REG 0x104 +#define MPI_SP0_REMAP_ENABLE_MASK (1 << 0) +#define MPI_SP1_RANGE_REG 0x10C +#define MPI_SP1_REMAP_REG 0x110 +#define MPI_SP1_REMAP_ENABLE_MASK (1 << 0) + +#define MPI_L2PCFG_REG 0x11c +#define MPI_L2PCFG_CFG_TYPE_SHIFT 0 +#define MPI_L2PCFG_CFG_TYPE_MASK (0x3 << MPI_L2PCFG_CFG_TYPE_SHIFT) +#define MPI_L2PCFG_REG_SHIFT 2 +#define MPI_L2PCFG_REG_MASK (0x3f << MPI_L2PCFG_REG_SHIFT) +#define MPI_L2PCFG_FUNC_SHIFT 8 +#define MPI_L2PCFG_FUNC_MASK (0x7 << MPI_L2PCFG_FUNC_SHIFT) +#define MPI_L2PCFG_DEVNUM_SHIFT 11 +#define MPI_L2PCFG_DEVNUM_MASK (0x1f << MPI_L2PCFG_DEVNUM_SHIFT) +#define MPI_L2PCFG_CFG_USEREG_MASK (1 << 30) +#define MPI_L2PCFG_CFG_SEL_MASK (1 << 31) + +#define MPI_L2PMEMRANGE1_REG 0x120 +#define MPI_L2PMEMBASE1_REG 0x124 +#define MPI_L2PMEMREMAP1_REG 0x128 +#define MPI_L2PMEMRANGE2_REG 0x12C +#define MPI_L2PMEMBASE2_REG 0x130 +#define MPI_L2PMEMREMAP2_REG 0x134 +#define MPI_L2PIORANGE_REG 0x138 +#define MPI_L2PIOBASE_REG 0x13C +#define MPI_L2PIOREMAP_REG 0x140 +#define MPI_L2P_BASE_MASK (0xffff8000) +#define MPI_L2PREMAP_ENABLED_MASK (1 << 0) +#define MPI_L2PREMAP_IS_CARDBUS_MASK (1 << 2) + +#define MPI_PCIMODESEL_REG 0x144 +#define MPI_PCIMODESEL_BAR1_NOSWAP_MASK (1 << 0) +#define MPI_PCIMODESEL_BAR2_NOSWAP_MASK (1 << 1) +#define MPI_PCIMODESEL_EXT_ARB_MASK (1 << 2) +#define MPI_PCIMODESEL_PREFETCH_SHIFT 4 +#define MPI_PCIMODESEL_PREFETCH_MASK (0xf << MPI_PCIMODESEL_PREFETCH_SHIFT) + +#define MPI_LOCBUSCTL_REG 0x14c +#define MPI_LOCBUSCTL_EN_PCI_GPIO_MASK (1 << 0) +#define MPI_LOCBUSCTL_U2P_NOSWAP_MASK (1 << 1) + +#define MPI_LOCINT_REG 0x150 +#define MPI_LOCINT_MASK(x) (1 << (x + 16)) +#define MPI_LOCINT_STAT(x) (1 << (x)) +#define MPI_LOCINT_DIR_FAILED 6 +#define MPI_LOCINT_EXT_PCI_INT 7 +#define MPI_LOCINT_SERR 8 +#define MPI_LOCINT_CSERR 9 + +#define MPI_PCICFGCTL_REG 0x178 +#define MPI_PCICFGCTL_CFGADDR_SHIFT 2 +#define MPI_PCICFGCTL_CFGADDR_MASK (0x1f << MPI_PCICFGCTL_CFGADDR_SHIFT) +#define MPI_PCICFGCTL_WRITEEN_MASK (1 << 7) + +#define MPI_PCICFGDATA_REG 0x17c + +#define PCMCIA_OFFSET 0x54 + +#define PCMCIA_C1_REG 0x0 +#define PCMCIA_C1_CD1_MASK (1 << 0) +#define PCMCIA_C1_CD2_MASK (1 << 1) +#define PCMCIA_C1_VS1_MASK (1 << 2) +#define PCMCIA_C1_VS2_MASK (1 << 3) +#define PCMCIA_C1_VS1OE_MASK (1 << 6) +#define PCMCIA_C1_VS2OE_MASK (1 << 7) +#define PCMCIA_C1_CBIDSEL_SHIFT (8) +#define PCMCIA_C1_CBIDSEL_MASK (0x1f << PCMCIA_C1_CBIDSEL_SHIFT) +#define PCMCIA_C1_EN_PCMCIA_GPIO_MASK (1 << 13) +#define PCMCIA_C1_EN_PCMCIA_MASK (1 << 14) +#define PCMCIA_C1_EN_CARDBUS_MASK (1 << 15) +#define PCMCIA_C1_RESET_MASK (1 << 18) + +#ifdef CONFIG_CARDBUS +struct bcm6348_cb { + u16 pci_command; + u8 cb_latency; + u8 subordinate_busn; + u8 cardbus_busn; + u8 pci_busn; + int bus_assigned; + u16 bridge_control; + + u32 mem_base0; + u32 mem_limit0; + u32 mem_base1; + u32 mem_limit1; + + u32 io_base0; + u32 io_limit0; + u32 io_base1; + u32 io_limit1; +}; +#endif /* CONFIG_CARDBUS */ + +struct bcm6348_pci { + void __iomem *pci; + void __iomem *pcmcia; + void __iomem *io; + int irq; + struct reset_control *reset; + bool remap; +#ifdef CONFIG_CARDBUS + struct bcm6348_cb cb; + int cb_bus; +#endif /* CONFIG_CARDBUS */ +}; + +static struct bcm6348_pci bcm6348_pci; + +extern int bmips_pci_irq; + +static u32 bcm6348_int_cfg_readl(u32 reg) +{ + struct bcm6348_pci *priv = &bcm6348_pci; + u32 tmp; + + tmp = reg & MPI_PCICFGCTL_CFGADDR_MASK; + tmp |= MPI_PCICFGCTL_WRITEEN_MASK; + __raw_writel(tmp, priv->pci + MPI_PCICFGCTL_REG); + iob(); + return __raw_readl(priv->pci + MPI_PCICFGDATA_REG); +} + +static void bcm6348_int_cfg_writel(u32 val, u32 reg) +{ + struct bcm6348_pci *priv = &bcm6348_pci; + u32 tmp; + + tmp = reg & MPI_PCICFGCTL_CFGADDR_MASK; + tmp |= MPI_PCICFGCTL_WRITEEN_MASK; + __raw_writel(tmp, priv->pci + MPI_PCICFGCTL_REG); + __raw_writel(val, priv->pci + MPI_PCICFGDATA_REG); +} + +/* + * swizzle 32bits data to return only the needed part + */ +static int postprocess_read(u32 data, int where, unsigned int size) +{ + u32 ret = 0; + + switch (size) { + case 1: + ret = (data >> ((where & 3) << 3)) & 0xff; + break; + case 2: + ret = (data >> ((where & 3) << 3)) & 0xffff; + break; + case 4: + ret = data; + break; + } + + return ret; +} + +static int preprocess_write(u32 orig_data, u32 val, int where, + unsigned int size) +{ + u32 ret = 0; + + switch (size) { + case 1: + ret = (orig_data & ~(0xff << ((where & 3) << 3))) | + (val << ((where & 3) << 3)); + break; + case 2: + ret = (orig_data & ~(0xffff << ((where & 3) << 3))) | + (val << ((where & 3) << 3)); + break; + case 4: + ret = val; + break; + } + + return ret; +} + +static int bcm6348_setup_cfg_access(int type, unsigned int busn, + unsigned int devfn, int where) +{ + struct bcm6348_pci *priv = &bcm6348_pci; + unsigned int slot, func, reg; + u32 val; + + slot = PCI_SLOT(devfn); + func = PCI_FUNC(devfn); + reg = where >> 2; + + /* sanity check */ + if (slot > (MPI_L2PCFG_DEVNUM_MASK >> MPI_L2PCFG_DEVNUM_SHIFT)) + return 1; + + if (func > (MPI_L2PCFG_FUNC_MASK >> MPI_L2PCFG_FUNC_SHIFT)) + return 1; + + if (reg > (MPI_L2PCFG_REG_MASK >> MPI_L2PCFG_REG_SHIFT)) + return 1; + + /* ok, setup config access */ + val = (reg << MPI_L2PCFG_REG_SHIFT); + val |= (func << MPI_L2PCFG_FUNC_SHIFT); + val |= (slot << MPI_L2PCFG_DEVNUM_SHIFT); + val |= MPI_L2PCFG_CFG_USEREG_MASK; + val |= MPI_L2PCFG_CFG_SEL_MASK; + /* type 0 cycle for local bus, type 1 cycle for anything else */ + if (type != 0) { + /* FIXME: how to specify bus ??? */ + val |= (1 << MPI_L2PCFG_CFG_TYPE_SHIFT); + } + __raw_writel(val, priv->pci + MPI_L2PCFG_REG); + + return 0; +} + + +static int bcm6348_do_cfg_read(int type, unsigned int busn, + unsigned int devfn, int where, int size, + u32 *val) +{ + struct bcm6348_pci *priv = &bcm6348_pci; + u32 data; + + /* two phase cycle, first we write address, then read data at + * another location, caller already has a spinlock so no need + * to add one here */ + if (bcm6348_setup_cfg_access(type, busn, devfn, where)) + return PCIBIOS_DEVICE_NOT_FOUND; + iob(); + data = le32_to_cpu(__raw_readl(priv->io)); + /* restore IO space normal behaviour */ + __raw_writel(0, priv->pci + MPI_L2PCFG_REG); + + *val = postprocess_read(data, where, size); + + return PCIBIOS_SUCCESSFUL; +} + +static int bcm6348_do_cfg_write(int type, unsigned int busn, + unsigned int devfn, int where, int size, + u32 val) +{ + struct bcm6348_pci *priv = &bcm6348_pci; + u32 data; + + /* two phase cycle, first we write address, then write data to + * another location, caller already has a spinlock so no need + * to add one here */ + if (bcm6348_setup_cfg_access(type, busn, devfn, where)) + return PCIBIOS_DEVICE_NOT_FOUND; + iob(); + + data = le32_to_cpu(__raw_readl(priv->io)); + data = preprocess_write(data, val, where, size); + + __raw_writel(cpu_to_le32(data), priv->io); + wmb(); + /* no way to know the access is done, we have to wait */ + udelay(500); + /* restore IO space normal behaviour */ + __raw_writel(0, priv->pci + MPI_L2PCFG_REG); + + return PCIBIOS_SUCCESSFUL; +} + +static int bcm6348_pci_read(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 *val) +{ + int type; + + type = bus->parent ? 1 : 0; + + if (type == 0 && PCI_SLOT(devfn) == CARDBUS_PCI_IDSEL) + return PCIBIOS_DEVICE_NOT_FOUND; + + return bcm6348_do_cfg_read(type, bus->number, devfn, + where, size, val); +} + +static int bcm6348_pci_write(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 val) +{ + int type; + + type = bus->parent ? 1 : 0; + + if (type == 0 && PCI_SLOT(devfn) == CARDBUS_PCI_IDSEL) + return PCIBIOS_DEVICE_NOT_FOUND; + + return bcm6348_do_cfg_write(type, bus->number, devfn, + where, size, val); +} + +static struct pci_ops bcm6348_pci_ops = { + .read = bcm6348_pci_read, + .write = bcm6348_pci_write, +}; + +static struct resource bcm6348_pci_io_resource = { + .name = "BCM6348 PCI IO space", + .flags = IORESOURCE_IO, +}; +static struct resource bcm6348_pci_mem_resource; +static struct resource bcm6348_pci_busn_resource; + +static struct pci_controller bcm6348_pci_controller = { + .pci_ops = &bcm6348_pci_ops, + .io_resource = &bcm6348_pci_io_resource, + .mem_resource = &bcm6348_pci_mem_resource, + .busn_resource = &bcm6348_pci_busn_resource, +}; + +#ifdef CONFIG_CARDBUS +static int bcm6348_cb_bridge_read(int where, int size, u32 *val) +{ + struct bcm6348_cb *cb = &bcm6348_pci.cb; + unsigned int reg; + u32 data; + + data = 0; + reg = where >> 2; + switch (reg) { + case (PCI_VENDOR_ID >> 2): + case (PCI_CB_SUBSYSTEM_VENDOR_ID >> 2): + /* create dummy vendor/device id from our cpu id */ + data = (CARDBUS_DUMMY_ID << 16) | PCI_VENDOR_ID_BROADCOM; + break; + + case (PCI_COMMAND >> 2): + data = (PCI_STATUS_DEVSEL_SLOW << 16); + data |= cb->pci_command; + break; + + case (PCI_CLASS_REVISION >> 2): + data = (PCI_CLASS_BRIDGE_CARDBUS << 16); + break; + + case (PCI_CACHE_LINE_SIZE >> 2): + data = (PCI_HEADER_TYPE_CARDBUS << 16); + break; + + case (PCI_INTERRUPT_LINE >> 2): + /* bridge control */ + data = (cb->bridge_control << 16); + /* pin:intA line:0xff */ + data |= (0x1 << 8) | 0xff; + break; + + case (PCI_CB_PRIMARY_BUS >> 2): + data = (cb->cb_latency << 24); + data |= (cb->subordinate_busn << 16); + data |= (cb->cardbus_busn << 8); + data |= cb->pci_busn; + break; + + case (PCI_CB_MEMORY_BASE_0 >> 2): + data = cb->mem_base0; + break; + + case (PCI_CB_MEMORY_LIMIT_0 >> 2): + data = cb->mem_limit0; + break; + + case (PCI_CB_MEMORY_BASE_1 >> 2): + data = cb->mem_base1; + break; + + case (PCI_CB_MEMORY_LIMIT_1 >> 2): + data = cb->mem_limit1; + break; + + case (PCI_CB_IO_BASE_0 >> 2): + /* | 1 for 32bits io support */ + data = cb->io_base0 | 0x1; + break; + + case (PCI_CB_IO_LIMIT_0 >> 2): + data = cb->io_limit0; + break; + + case (PCI_CB_IO_BASE_1 >> 2): + /* | 1 for 32bits io support */ + data = cb->io_base1 | 0x1; + break; + + case (PCI_CB_IO_LIMIT_1 >> 2): + data = cb->io_limit1; + break; + } + + *val = postprocess_read(data, where, size); + return PCIBIOS_SUCCESSFUL; +} + +/* + * emulate configuration write access on a cardbus bridge + */ +static int bcm6348_cb_bridge_write(int where, int size, u32 val) +{ + struct bcm6348_cb *cb = &bcm6348_pci.cb; + unsigned int reg; + u32 data, tmp; + int ret; + + ret = bcm6348_cb_bridge_read((where & ~0x3), 4, &data); + if (ret != PCIBIOS_SUCCESSFUL) + return ret; + + data = preprocess_write(data, val, where, size); + + reg = where >> 2; + switch (reg) { + case (PCI_COMMAND >> 2): + cb->pci_command = (data & 0xffff); + break; + + case (PCI_CB_PRIMARY_BUS >> 2): + cb->cb_latency = (data >> 24) & 0xff; + cb->subordinate_busn = (data >> 16) & 0xff; + cb->cardbus_busn = (data >> 8) & 0xff; + cb->pci_busn = data & 0xff; + if (cb->cardbus_busn) + cb->bus_assigned = 1; + break; + + case (PCI_INTERRUPT_LINE >> 2): + tmp = (data >> 16) & 0xffff; + /* Disable memory prefetch support */ + tmp &= ~PCI_CB_BRIDGE_CTL_PREFETCH_MEM0; + tmp &= ~PCI_CB_BRIDGE_CTL_PREFETCH_MEM1; + cb->bridge_control = tmp; + break; + + case (PCI_CB_MEMORY_BASE_0 >> 2): + cb->mem_base0 = data; + break; + + case (PCI_CB_MEMORY_LIMIT_0 >> 2): + cb->mem_limit0 = data; + break; + + case (PCI_CB_MEMORY_BASE_1 >> 2): + cb->mem_base1 = data; + break; + + case (PCI_CB_MEMORY_LIMIT_1 >> 2): + cb->mem_limit1 = data; + break; + + case (PCI_CB_IO_BASE_0 >> 2): + cb->io_base0 = data; + break; + + case (PCI_CB_IO_LIMIT_0 >> 2): + cb->io_limit0 = data; + break; + + case (PCI_CB_IO_BASE_1 >> 2): + cb->io_base1 = data; + break; + + case (PCI_CB_IO_LIMIT_1 >> 2): + cb->io_limit1 = data; + break; + } + + return PCIBIOS_SUCCESSFUL; +} + +static int bcm6348_cb_read(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 *val) +{ + struct bcm6348_pci *priv = &bcm6348_pci; + struct bcm6348_cb *cb = &priv->cb; + + /* Snoop access to slot 0x1e on root bus, we fake a cardbus + * bridge at this location */ + if (!bus->parent && PCI_SLOT(devfn) == FAKE_CB_BRIDGE_SLOT) { + priv->cb_bus = bus->number; + return bcm6348_cb_bridge_read(where, size, val); + } + + /* A configuration cycle for the device behind the cardbus + * bridge is actually done as a type 0 cycle on the primary + * bus. This means that only one device can be on the cardbus + * bus */ + if (cb->bus_assigned && + bus->number == cb->cardbus_busn && + PCI_SLOT(devfn) == 0) + return bcm6348_do_cfg_read(0, 0, + PCI_DEVFN(CARDBUS_PCI_IDSEL, 0), + where, size, val); + + return PCIBIOS_DEVICE_NOT_FOUND; +} + +static int bcm6348_cb_write(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 val) +{ + struct bcm6348_pci *priv = &bcm6348_pci; + struct bcm6348_cb *cb = &priv->cb; + + if (!bus->parent && PCI_SLOT(devfn) == FAKE_CB_BRIDGE_SLOT) { + priv->cb_bus = bus->number; + return bcm6348_cb_bridge_write(where, size, val); + } + + if (cb->bus_assigned && + bus->number == cb->cardbus_busn && + PCI_SLOT(devfn) == 0) + return bcm6348_do_cfg_write(0, 0, + PCI_DEVFN(CARDBUS_PCI_IDSEL, 0), + where, size, val); + + return PCIBIOS_DEVICE_NOT_FOUND; +} + +static struct pci_ops bcm6348_cb_ops = { + .read = bcm6348_cb_read, + .write = bcm6348_cb_write, +}; + +/* + * only one IO window, so it cannot be shared by PCI and cardbus, use + * fixup to choose and detect unhandled configuration + */ +static void bcm6348_pci_fixup(struct pci_dev *dev) +{ + struct bcm6348_pci *priv = &bcm6348_pci; + struct bcm6348_cb *cb = &priv->cb; + static int io_window = -1; + int i, found, new_io_window; + u32 val; + + /* look for any io resource */ + found = 0; + for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { + if (pci_resource_flags(dev, i) & IORESOURCE_IO) { + found = 1; + break; + } + } + + if (!found) + return; + + /* skip our fake bus with only cardbus bridge on it */ + if (dev->bus->number == priv->cb_bus) + return; + + /* find on which bus the device is */ + if (cb->bus_assigned && + dev->bus->number == cb->cardbus_busn && + PCI_SLOT(dev->devfn) == 0) + new_io_window = 1; + else + new_io_window = 0; + + if (new_io_window == io_window) + return; + + if (io_window != -1) { + pr_err("bcm63xx: both PCI and cardbus devices " + "need IO, which hardware cannot do\n"); + return; + } + + pr_info("bcm63xx: PCI IO window assigned to %s\n", + (new_io_window == 0) ? "PCI" : "cardbus"); + + val = __raw_readl(priv->pci + MPI_L2PIOREMAP_REG); + if (io_window) + val |= MPI_L2PREMAP_IS_CARDBUS_MASK; + else + val &= ~MPI_L2PREMAP_IS_CARDBUS_MASK; + __raw_writel(val, priv->pci + MPI_L2PIOREMAP_REG); + + io_window = new_io_window; +} +DECLARE_PCI_FIXUP_ENABLE(PCI_ANY_ID, PCI_ANY_ID, bcm6348_pci_fixup); + +static struct resource bcm6348_cb_io_resource = { + .name = "bcm6348 CB IO space", + .flags = IORESOURCE_IO, +}; +static struct resource bcm6348_cb_mem_resource; + +static struct pci_controller bcm6348_cb_controller = { + .pci_ops = &bcm6348_cb_ops, + .io_resource = &bcm6348_cb_io_resource, + .mem_resource = &bcm6348_cb_mem_resource, +}; +#endif /* CONFIG_CARDBUS */ + +static void bcm6348_pci_setup(struct bcm6348_pci *priv) +{ + u32 val; + + /* Setup local bus to PCI access (PCI memory) */ + val = bcm6348_pci_mem_resource.start & MPI_L2P_BASE_MASK; + __raw_writel(val, priv->pci + MPI_L2PMEMBASE1_REG); + __raw_writel(~(resource_size(&bcm6348_pci_mem_resource) - 1), + priv->pci + MPI_L2PMEMRANGE1_REG); + __raw_writel(val | MPI_L2PREMAP_ENABLED_MASK, + priv->pci + MPI_L2PMEMREMAP1_REG); + + /* Set Cardbus IDSEL (type 0 cfg access on primary bus for + * this IDSEL will be done on Cardbus instead) */ + val = __raw_readl(priv->pcmcia + PCMCIA_C1_REG); + val &= ~PCMCIA_C1_CBIDSEL_MASK; + val |= (CARDBUS_PCI_IDSEL << PCMCIA_C1_CBIDSEL_SHIFT); + __raw_writel(val, priv->pcmcia + PCMCIA_C1_REG); + +#ifdef CONFIG_CARDBUS + /* setup local bus to PCI access (Cardbus memory) */ + val = bcm6348_cb_mem_resource.start & MPI_L2P_BASE_MASK; + __raw_writel(val, priv->pci + MPI_L2PMEMBASE2_REG); + __raw_writel(~(resource_size(&bcm6348_cb_mem_resource) - 1), + priv->pci + MPI_L2PMEMRANGE2_REG); + val |= MPI_L2PREMAP_ENABLED_MASK | MPI_L2PREMAP_IS_CARDBUS_MASK; + __raw_writel(val, priv->pci + MPI_L2PMEMREMAP2_REG); +#else + /* disable second access windows */ + __raw_writel(0, priv->pci + MPI_L2PMEMREMAP2_REG); +#endif + + /* setup local bus to PCI access (IO memory), we have only 1 + * IO window for both PCI and cardbus, but it cannot handle + * both at the same time, assume standard PCI for now, if + * cardbus card has IO zone, PCI fixup will change window to + * cardbus */ + val = bcm6348_pci_io_resource.start & MPI_L2P_BASE_MASK; + __raw_writel(val, priv->pci + MPI_L2PIOBASE_REG); + __raw_writel(~(resource_size(&bcm6348_pci_io_resource) - 1), + priv->pci + MPI_L2PIORANGE_REG); + __raw_writel(val | MPI_L2PREMAP_ENABLED_MASK, + priv->pci + MPI_L2PIOREMAP_REG); + + /* Enable PCI related GPIO pins */ + __raw_writel(MPI_LOCBUSCTL_EN_PCI_GPIO_MASK, + priv->pci + MPI_LOCBUSCTL_REG); + + /* Setup PCI to local bus access, used by PCI device to target + * local RAM while bus mastering */ + bcm6348_int_cfg_writel(0, PCI_BASE_ADDRESS_3); + if (priv->remap) + val = MPI_SP0_REMAP_ENABLE_MASK; + else + val = 0; + __raw_writel(val, priv->pci + MPI_SP0_REMAP_REG); + + bcm6348_int_cfg_writel(0, PCI_BASE_ADDRESS_4); + __raw_writel(0, priv->pci + MPI_SP1_REMAP_REG); + + /* Setup sp0 range to local RAM size */ + __raw_writel(~(memblock_phys_mem_size() - 1), + priv->pci + MPI_SP0_RANGE_REG); + __raw_writel(0, priv->pci + MPI_SP1_RANGE_REG); + + /* Change host bridge retry counter to infinite number of + * retries, needed for some broadcom wifi cards with Silicon + * Backplane bus where access to srom seems very slow */ + val = bcm6348_int_cfg_readl(BCMPCI_REG_TIMERS); + val &= ~REG_TIMER_RETRY_MASK; + bcm6348_int_cfg_writel(val, BCMPCI_REG_TIMERS); + + /* EEnable memory decoder and bus mastering */ + val = bcm6348_int_cfg_readl(PCI_COMMAND); + val |= (PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); + bcm6348_int_cfg_writel(val, PCI_COMMAND); + + /* Enable read prefetching & disable byte swapping for bus + * mastering transfers */ + val = __raw_readl(priv->pci + MPI_PCIMODESEL_REG); + val &= ~MPI_PCIMODESEL_BAR1_NOSWAP_MASK; + val &= ~MPI_PCIMODESEL_BAR2_NOSWAP_MASK; + val &= ~MPI_PCIMODESEL_PREFETCH_MASK; + val |= (8 << MPI_PCIMODESEL_PREFETCH_SHIFT); + __raw_writel(val, priv->pci + MPI_PCIMODESEL_REG); + + /* Enable pci interrupt */ + val = __raw_readl(priv->pci + MPI_LOCINT_REG); + val |= MPI_LOCINT_MASK(MPI_LOCINT_EXT_PCI_INT); + __raw_writel(val, priv->pci + MPI_LOCINT_REG); +} + +static int bcm6348_pci_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct bcm6348_pci *priv = &bcm6348_pci; + struct resource *res; + + of_pci_check_probe_only(); + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pci"); + priv->pci = devm_ioremap_resource(dev, res); + if (IS_ERR(priv->pci)) + return PTR_ERR(priv->pci); + + priv->pcmcia = priv->pci + PCMCIA_OFFSET; + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pci-io"); + if (!res) + return -EINVAL; +#ifdef CONFIG_CARDBUS + bcm6348_pci_io_resource.start = res->start; + bcm6348_pci_io_resource.end = res->end - (resource_size(res) >> 1); + bcm6348_cb_io_resource.start = res->start + (resource_size(res) >> 1); + bcm6348_cb_io_resource.end = res->end; +#else + bcm6348_pci_io_resource.start = res->start; + bcm6348_pci_io_resource.end = res->end; +#endif + + priv->irq = platform_get_irq(pdev, 0); + if (!priv->irq) + return -ENODEV; + + bmips_pci_irq = priv->irq; + + priv->reset = devm_reset_control_get(dev, "pci"); + if (IS_ERR(priv->reset)) + return PTR_ERR(priv->reset); + + priv->remap = of_property_read_bool(np, "brcm,remap"); + + reset_control_reset(priv->reset); + + pci_load_of_ranges(&bcm6348_pci_controller, np); + if (!bcm6348_pci_mem_resource.start) + return -EINVAL; + + of_pci_parse_bus_range(np, &bcm6348_pci_busn_resource); + + /* + * Configuration accesses are done through IO space, remap 4 + * first bytes to access it from CPU. + * + * This means that no IO access from CPU should happen while + * we do a configuration cycle, but there's no way we can add + * a spinlock for each io access, so this is currently kind of + * broken on SMP. + */ + priv->io = ioremap(bcm6348_pci_io_resource.start, sizeof(u32)); + if (!priv->io) + return -ENOMEM; + + bcm6348_pci_setup(priv); + + register_pci_controller(&bcm6348_pci_controller); + +#ifdef CONFIG_CARDBUS + priv->cb_bus = -1; + register_pci_controller(&bcm6348_cb_controller); +#endif /* CONFIG_CARDBUS */ + + /* Mark memory space used for IO mapping as reserved */ + request_mem_region(bcm6348_pci_io_resource.start, + resource_size(&bcm6348_pci_io_resource), + "BCM6348 PCI IO space"); + + return 0; +} + +static const struct of_device_id bcm6348_pci_of_match[] = { + { .compatible = "brcm,bcm6348-pci", }, + { /* sentinel */ } +}; + +static struct platform_driver bcm6348_pci_driver = { + .probe = bcm6348_pci_probe, + .driver = { + .name = "bcm6348-pci", + .of_match_table = bcm6348_pci_of_match, + }, +}; + +int __init bcm6348_pci_init(void) +{ + int ret = platform_driver_register(&bcm6348_pci_driver); + if (ret) + pr_err("pci-bcm6348: Error registering platform driver!\n"); + return ret; +} +late_initcall_sync(bcm6348_pci_init); diff --git a/target/linux/bmips/files/drivers/pci/controller/pcie-bcm6318.c b/target/linux/bmips/files/drivers/pci/controller/pcie-bcm6318.c new file mode 100644 index 0000000000..1df67b8389 --- /dev/null +++ b/target/linux/bmips/files/drivers/pci/controller/pcie-bcm6318.c @@ -0,0 +1,402 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * BCM6318 PCIe Controller Driver + * + * Copyright (C) 2020 Álvaro Fernández Rojas + * Copyright (C) 2015 Jonas Gorski + * Copyright (C) 2008 Maxime Bizon + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../pci.h" + +#define PCIE_BUS_BRIDGE 0 +#define PCIE_BUS_DEVICE 1 + +#define PCIE_SPECIFIC_REG 0x188 +#define SPECIFIC_ENDIAN_MODE_BAR1_SHIFT 0 +#define SPECIFIC_ENDIAN_MODE_BAR1_MASK (0x3 << SPECIFIC_ENDIAN_MODE_BAR1_SHIFT) +#define SPECIFIC_ENDIAN_MODE_BAR2_SHIFT 2 +#define SPECIFIC_ENDIAN_MODE_BAR2_MASK (0x3 << SPECIFIC_ENDIAN_MODE_BAR1_SHIFT) +#define SPECIFIC_ENDIAN_MODE_BAR3_SHIFT 4 +#define SPECIFIC_ENDIAN_MODE_BAR3_MASK (0x3 << SPECIFIC_ENDIAN_MODE_BAR1_SHIFT) +#define SPECIFIC_ENDIAN_MODE_WORD_ALIGN 0 +#define SPECIFIC_ENDIAN_MODE_HALFWORD_ALIGN 1 +#define SPECIFIC_ENDIAN_MODE_BYTE_ALIGN 2 + +#define PCIE_CONFIG2_REG 0x408 +#define CONFIG2_BAR1_SIZE_EN 1 +#define CONFIG2_BAR1_SIZE_MASK 0xf + +#define PCIE_IDVAL3_REG 0x43c +#define IDVAL3_CLASS_CODE_MASK 0xffffff +#define IDVAL3_SUBCLASS_SHIFT 8 +#define IDVAL3_CLASS_SHIFT 16 + +#define PCIE_DLSTATUS_REG 0x1048 +#define DLSTATUS_PHYLINKUP (1 << 13) + +#define PCIE_CPU_2_PCIE_MEM_WIN0_LO_REG 0x400c +#define C2P_MEM_WIN_ENDIAN_MODE_MASK 0x3 +#define C2P_MEM_WIN_ENDIAN_NO_SWAP 0 +#define C2P_MEM_WIN_ENDIAN_HALF_WORD_SWAP 1 +#define C2P_MEM_WIN_ENDIAN_HALF_BYTE_SWAP 2 +#define C2P_MEM_WIN_BASE_ADDR_SHIFT 20 +#define C2P_MEM_WIN_BASE_ADDR_MASK (0xfff << C2P_MEM_WIN_BASE_ADDR_SHIFT) + +#define PCIE_RC_BAR1_CONFIG_LO_REG 0x402c +#define RC_BAR_CFG_LO_SIZE_256MB 0xd +#define RC_BAR_CFG_LO_MATCH_ADDR_SHIFT 20 +#define RC_BAR_CFG_LO_MATCH_ADDR_MASK (0xfff << RC_BAR_CFG_LO_MATCH_ADDR_SHIFT) + +#define PCIE_CPU_2_PCIE_MEM_WIN0_BASELIMIT_REG 0x4070 +#define C2P_BASELIMIT_LIMIT_SHIFT 20 +#define C2P_BASELIMIT_LIMIT_MASK (0xfff << C2P_BASELIMIT_LIMIT_SHIFT) +#define C2P_BASELIMIT_BASE_SHIFT 4 +#define C2P_BASELIMIT_BASE_MASK (0xfff << C2P_BASELIMIT_BASE_SHIFT) + +#define PCIE_UBUS_BAR1_CFG_REMAP_REG 0x4088 +#define BAR1_CFG_REMAP_OFFSET_SHIFT 20 +#define BAR1_CFG_REMAP_OFFSET_MASK (0xfff << BAR1_CFG_REMAP_OFFSET_SHIFT) +#define BAR1_CFG_REMAP_ACCESS_EN 1 + +#define PCIE_HARD_DEBUG_REG 0x4204 +#define HARD_DEBUG_SERDES_IDDQ (1 << 23) + +#define PCIE_CPU_INT1_MASK_CLEAR_REG 0x830c +#define CPU_INT_PCIE_ERR_ATTN_CPU (1 << 0) +#define CPU_INT_PCIE_INTA (1 << 1) +#define CPU_INT_PCIE_INTB (1 << 2) +#define CPU_INT_PCIE_INTC (1 << 3) +#define CPU_INT_PCIE_INTD (1 << 4) +#define CPU_INT_PCIE_INTR (1 << 5) +#define CPU_INT_PCIE_NMI (1 << 6) +#define CPU_INT_PCIE_UBUS (1 << 7) +#define CPU_INT_IPI (1 << 8) + +#define PCIE_EXT_CFG_INDEX_REG 0x8400 +#define EXT_CFG_FUNC_NUM_SHIFT 12 +#define EXT_CFG_FUNC_NUM_MASK (0x7 << EXT_CFG_FUNC_NUM_SHIFT) +#define EXT_CFG_DEV_NUM_SHIFT 15 +#define EXT_CFG_DEV_NUM_MASK (0xf << EXT_CFG_DEV_NUM_SHIFT) +#define EXT_CFG_BUS_NUM_SHIFT 20 +#define EXT_CFG_BUS_NUM_MASK (0xff << EXT_CFG_BUS_NUM_SHIFT) + +#define PCIE_DEVICE_OFFSET 0x9000 + +struct bcm6318_pcie { + void __iomem *base; + int irq; + struct clk *clk; + struct clk *clk25; + struct clk *clk_ubus; + struct reset_control *reset; + struct reset_control *reset_ext; + struct reset_control *reset_core; + struct reset_control *reset_hard; +}; + +static struct bcm6318_pcie bcm6318_pcie; + +extern int bmips_pci_irq; + +/* + * swizzle 32bits data to return only the needed part + */ +static int postprocess_read(u32 data, int where, unsigned int size) +{ + u32 ret = 0; + + switch (size) { + case 1: + ret = (data >> ((where & 3) << 3)) & 0xff; + break; + case 2: + ret = (data >> ((where & 3) << 3)) & 0xffff; + break; + case 4: + ret = data; + break; + } + + return ret; +} + +static int preprocess_write(u32 orig_data, u32 val, int where, + unsigned int size) +{ + u32 ret = 0; + + switch (size) { + case 1: + ret = (orig_data & ~(0xff << ((where & 3) << 3))) | + (val << ((where & 3) << 3)); + break; + case 2: + ret = (orig_data & ~(0xffff << ((where & 3) << 3))) | + (val << ((where & 3) << 3)); + break; + case 4: + ret = val; + break; + } + + return ret; +} + +static int bcm6318_pcie_can_access(struct pci_bus *bus, int devfn) +{ + struct bcm6318_pcie *priv = &bcm6318_pcie; + + switch (bus->number) { + case PCIE_BUS_BRIDGE: + return PCI_SLOT(devfn) == 0; + case PCIE_BUS_DEVICE: + if (PCI_SLOT(devfn) == 0) + return __raw_readl(priv->base + PCIE_DLSTATUS_REG) + & DLSTATUS_PHYLINKUP; + /* else, fall through */ + default: + return false; + } +} + +static int bcm6318_pcie_read(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 *val) +{ + struct bcm6318_pcie *priv = &bcm6318_pcie; + u32 data; + u32 reg = where & ~3; + + if (!bcm6318_pcie_can_access(bus, devfn)) + return PCIBIOS_DEVICE_NOT_FOUND; + + if (bus->number == PCIE_BUS_DEVICE) + reg += PCIE_DEVICE_OFFSET; + + data = __raw_readl(priv->base + reg); + *val = postprocess_read(data, where, size); + + return PCIBIOS_SUCCESSFUL; +} + +static int bcm6318_pcie_write(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 val) +{ + struct bcm6318_pcie *priv = &bcm6318_pcie; + u32 data; + u32 reg = where & ~3; + + if (!bcm6318_pcie_can_access(bus, devfn)) + return PCIBIOS_DEVICE_NOT_FOUND; + + if (bus->number == PCIE_BUS_DEVICE) + reg += PCIE_DEVICE_OFFSET; + + data = __raw_readl(priv->base + reg); + data = preprocess_write(data, val, where, size); + __raw_writel(data, priv->base + reg); + + return PCIBIOS_SUCCESSFUL; +} + +static struct pci_ops bcm6318_pcie_ops = { + .read = bcm6318_pcie_read, + .write = bcm6318_pcie_write, +}; + +static struct resource bcm6318_pcie_io_resource; +static struct resource bcm6318_pcie_mem_resource; +static struct resource bcm6318_pcie_busn_resource; + +static struct pci_controller bcm6318_pcie_controller = { + .pci_ops = &bcm6318_pcie_ops, + .io_resource = &bcm6318_pcie_io_resource, + .mem_resource = &bcm6318_pcie_mem_resource, + .busn_resource = &bcm6318_pcie_busn_resource, +}; + +static void bcm6318_pcie_reset(struct bcm6318_pcie *priv) +{ + u32 val; + + reset_control_deassert(priv->reset_hard); + + reset_control_assert(priv->reset); + reset_control_assert(priv->reset_core); + reset_control_assert(priv->reset_ext); + mdelay(10); + + reset_control_deassert(priv->reset_ext); + mdelay(10); + + reset_control_deassert(priv->reset); + mdelay(10); + + val = __raw_readl(priv->base + PCIE_HARD_DEBUG_REG); + val &= ~HARD_DEBUG_SERDES_IDDQ; + __raw_writel(val, priv->base + PCIE_HARD_DEBUG_REG); + mdelay(10); + + reset_control_deassert(priv->reset_core); + mdelay(200); +} + +static void bcm6318_pcie_setup(struct bcm6318_pcie *priv) +{ + u32 val; + + __raw_writel(CPU_INT_PCIE_INTA | CPU_INT_PCIE_INTB | + CPU_INT_PCIE_INTC | CPU_INT_PCIE_INTD, + priv->base + PCIE_CPU_INT1_MASK_CLEAR_REG); + + val = bcm6318_pcie_mem_resource.end & C2P_BASELIMIT_LIMIT_MASK; + val |= (bcm6318_pcie_mem_resource.start >> C2P_BASELIMIT_LIMIT_SHIFT) + << C2P_BASELIMIT_BASE_SHIFT; + __raw_writel(val, priv->base + PCIE_CPU_2_PCIE_MEM_WIN0_BASELIMIT_REG); + + /* setup class code as bridge */ + val = __raw_readl(priv->base + PCIE_IDVAL3_REG); + val &= ~IDVAL3_CLASS_CODE_MASK; + val |= (PCI_CLASS_BRIDGE_PCI << IDVAL3_SUBCLASS_SHIFT); + __raw_writel(val, priv->base + PCIE_IDVAL3_REG); + + /* disable bar1 size */ + val = __raw_readl(priv->base + PCIE_CONFIG2_REG); + val &= ~CONFIG2_BAR1_SIZE_MASK; + __raw_writel(val, priv->base + PCIE_CONFIG2_REG); + + /* set bar0 to little endian */ + val = __raw_readl(priv->base + PCIE_CPU_2_PCIE_MEM_WIN0_LO_REG); + val |= bcm6318_pcie_mem_resource.start & C2P_MEM_WIN_BASE_ADDR_MASK; + val |= C2P_MEM_WIN_ENDIAN_HALF_BYTE_SWAP; + __raw_writel(val, priv->base + PCIE_CPU_2_PCIE_MEM_WIN0_LO_REG); + + __raw_writel(SPECIFIC_ENDIAN_MODE_BYTE_ALIGN, + priv->base + PCIE_SPECIFIC_REG); + + __raw_writel(RC_BAR_CFG_LO_SIZE_256MB, + priv->base + PCIE_RC_BAR1_CONFIG_LO_REG); + + __raw_writel(BAR1_CFG_REMAP_ACCESS_EN, + priv->base + PCIE_UBUS_BAR1_CFG_REMAP_REG); + + __raw_writel(PCIE_BUS_DEVICE << EXT_CFG_BUS_NUM_SHIFT, + priv->base + PCIE_EXT_CFG_INDEX_REG); +} + +static int bcm6318_pcie_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct bcm6318_pcie *priv = &bcm6318_pcie; + struct resource *res; + int ret; + + of_pci_check_probe_only(); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + priv->base = devm_ioremap_resource(dev, res); + if (IS_ERR(priv->base)) + return PTR_ERR(priv->base); + + priv->irq = platform_get_irq(pdev, 0); + if (!priv->irq) + return -ENODEV; + + bmips_pci_irq = priv->irq; + + priv->reset = devm_reset_control_get(dev, "pcie"); + if (IS_ERR(priv->reset)) + return PTR_ERR(priv->reset); + + priv->reset_ext = devm_reset_control_get(dev, "pcie-ext"); + if (IS_ERR(priv->reset_ext)) + return PTR_ERR(priv->reset_ext); + + priv->reset_core = devm_reset_control_get(dev, "pcie-core"); + if (IS_ERR(priv->reset_core)) + return PTR_ERR(priv->reset_core); + + priv->reset_hard = devm_reset_control_get(dev, "pcie-hard"); + if (IS_ERR(priv->reset_hard)) + return PTR_ERR(priv->reset_hard); + + priv->clk = devm_clk_get(dev, "pcie"); + if (IS_ERR(priv->clk)) + return PTR_ERR(priv->clk); + + priv->clk25 = devm_clk_get(dev, "pcie25"); + if (IS_ERR(priv->clk25)) + return PTR_ERR(priv->clk25); + + priv->clk_ubus = devm_clk_get(dev, "pcie-ubus"); + if (IS_ERR(priv->clk_ubus)) + return PTR_ERR(priv->clk_ubus); + + ret = clk_prepare_enable(priv->clk); + if (ret) { + dev_err(dev, "could not enable clock\n"); + return ret; + } + + ret = clk_prepare_enable(priv->clk25); + if (ret) { + dev_err(dev, "could not enable clock\n"); + return ret; + } + + ret = clk_prepare_enable(priv->clk_ubus); + if (ret) { + dev_err(dev, "could not enable clock\n"); + return ret; + } + + pci_load_of_ranges(&bcm6318_pcie_controller, np); + if (!bcm6318_pcie_mem_resource.start) + return -EINVAL; + + of_pci_parse_bus_range(np, &bcm6318_pcie_busn_resource); + + bcm6318_pcie_reset(priv); + bcm6318_pcie_setup(priv); + + register_pci_controller(&bcm6318_pcie_controller); + + return 0; +} + +static const struct of_device_id bcm6318_pcie_of_match[] = { + { .compatible = "brcm,bcm6318-pcie", }, + { /* sentinel */ } +}; + +static struct platform_driver bcm6318_pcie_driver = { + .probe = bcm6318_pcie_probe, + .driver = { + .name = "bcm6318-pcie", + .of_match_table = bcm6318_pcie_of_match, + }, +}; + +int __init bcm6318_pcie_init(void) +{ + int ret = platform_driver_register(&bcm6318_pcie_driver); + if (ret) + pr_err("pci-bcm6318: Error registering platform driver!\n"); + return ret; +} +late_initcall_sync(bcm6318_pcie_init); diff --git a/target/linux/bmips/files/drivers/pci/controller/pcie-bcm6328.c b/target/linux/bmips/files/drivers/pci/controller/pcie-bcm6328.c new file mode 100644 index 0000000000..4c0d3723b8 --- /dev/null +++ b/target/linux/bmips/files/drivers/pci/controller/pcie-bcm6328.c @@ -0,0 +1,412 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * BCM6328 PCIe Controller Driver + * + * Copyright (C) 2020 Álvaro Fernández Rojas + * Copyright (C) 2015 Jonas Gorski + * Copyright (C) 2008 Maxime Bizon + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../pci.h" + +#define SERDES_PCIE_EXD_EN BIT(15) +#define SERDES_PCIE_EN BIT(0) + +#define PCIE_BUS_BRIDGE 0 +#define PCIE_BUS_DEVICE 1 + +#define PCIE_CONFIG2_REG 0x408 +#define CONFIG2_BAR1_SIZE_EN 1 +#define CONFIG2_BAR1_SIZE_MASK 0xf + +#define PCIE_IDVAL3_REG 0x43c +#define IDVAL3_CLASS_CODE_MASK 0xffffff +#define IDVAL3_SUBCLASS_SHIFT 8 +#define IDVAL3_CLASS_SHIFT 16 + +#define PCIE_DLSTATUS_REG 0x1048 +#define DLSTATUS_PHYLINKUP (1 << 13) + +#define PCIE_BRIDGE_OPT1_REG 0x2820 +#define OPT1_RD_BE_OPT_EN (1 << 7) +#define OPT1_RD_REPLY_BE_FIX_EN (1 << 9) +#define OPT1_PCIE_BRIDGE_HOLE_DET_EN (1 << 11) +#define OPT1_L1_INT_STATUS_MASK_POL (1 << 12) + +#define PCIE_BRIDGE_OPT2_REG 0x2824 +#define OPT2_UBUS_UR_DECODE_DIS (1 << 2) +#define OPT2_TX_CREDIT_CHK_EN (1 << 4) +#define OPT2_CFG_TYPE1_BD_SEL (1 << 7) +#define OPT2_CFG_TYPE1_BUS_NO_SHIFT 16 +#define OPT2_CFG_TYPE1_BUS_NO_MASK (0xff << OPT2_CFG_TYPE1_BUS_NO_SHIFT) + +#define PCIE_BRIDGE_BAR0_BASEMASK_REG 0x2828 +#define BASEMASK_REMAP_EN (1 << 0) +#define BASEMASK_SWAP_EN (1 << 1) +#define BASEMASK_MASK_SHIFT 4 +#define BASEMASK_MASK_MASK (0xfff << BASEMASK_MASK_SHIFT) +#define BASEMASK_BASE_SHIFT 20 +#define BASEMASK_BASE_MASK (0xfff << BASEMASK_BASE_SHIFT) + +#define PCIE_BRIDGE_BAR0_REBASE_ADDR_REG 0x282c +#define REBASE_ADDR_BASE_SHIFT 20 +#define REBASE_ADDR_BASE_MASK (0xfff << REBASE_ADDR_BASE_SHIFT) + +#define PCIE_BRIDGE_RC_INT_MASK_REG 0x2854 +#define PCIE_RC_INT_A (1 << 0) +#define PCIE_RC_INT_B (1 << 1) +#define PCIE_RC_INT_C (1 << 2) +#define PCIE_RC_INT_D (1 << 3) + +#define PCIE_DEVICE_OFFSET 0x8000 + +struct bcm6328_pcie { + void __iomem *base; + int irq; + struct regmap *serdes; + struct device **pm; + struct device_link **link_pm; + unsigned int num_pms; + struct clk *clk; + struct reset_control *reset; + struct reset_control *reset_ext; + struct reset_control *reset_core; + struct reset_control *reset_hard; +}; + +static struct bcm6328_pcie bcm6328_pcie; + +extern int bmips_pci_irq; + +/* + * swizzle 32bits data to return only the needed part + */ +static int postprocess_read(u32 data, int where, unsigned int size) +{ + u32 ret = 0; + + switch (size) { + case 1: + ret = (data >> ((where & 3) << 3)) & 0xff; + break; + case 2: + ret = (data >> ((where & 3) << 3)) & 0xffff; + break; + case 4: + ret = data; + break; + } + + return ret; +} + +static int preprocess_write(u32 orig_data, u32 val, int where, + unsigned int size) +{ + u32 ret = 0; + + switch (size) { + case 1: + ret = (orig_data & ~(0xff << ((where & 3) << 3))) | + (val << ((where & 3) << 3)); + break; + case 2: + ret = (orig_data & ~(0xffff << ((where & 3) << 3))) | + (val << ((where & 3) << 3)); + break; + case 4: + ret = val; + break; + } + + return ret; +} + +static int bcm6328_pcie_can_access(struct pci_bus *bus, int devfn) +{ + struct bcm6328_pcie *priv = &bcm6328_pcie; + + switch (bus->number) { + case PCIE_BUS_BRIDGE: + return PCI_SLOT(devfn) == 0; + case PCIE_BUS_DEVICE: + if (PCI_SLOT(devfn) == 0) + return __raw_readl(priv->base + PCIE_DLSTATUS_REG) + & DLSTATUS_PHYLINKUP; + /* else, fall through */ + default: + return false; + } +} + +static int bcm6328_pcie_read(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 *val) +{ + struct bcm6328_pcie *priv = &bcm6328_pcie; + u32 data; + u32 reg = where & ~3; + + if (!bcm6328_pcie_can_access(bus, devfn)) + return PCIBIOS_DEVICE_NOT_FOUND; + + if (bus->number == PCIE_BUS_DEVICE) + reg += PCIE_DEVICE_OFFSET; + + data = __raw_readl(priv->base + reg); + *val = postprocess_read(data, where, size); + + return PCIBIOS_SUCCESSFUL; +} + +static int bcm6328_pcie_write(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 val) +{ + struct bcm6328_pcie *priv = &bcm6328_pcie; + u32 data; + u32 reg = where & ~3; + + if (!bcm6328_pcie_can_access(bus, devfn)) + return PCIBIOS_DEVICE_NOT_FOUND; + + if (bus->number == PCIE_BUS_DEVICE) + reg += PCIE_DEVICE_OFFSET; + + data = __raw_readl(priv->base + reg); + data = preprocess_write(data, val, where, size); + __raw_writel(data, priv->base + reg); + + return PCIBIOS_SUCCESSFUL; +} + +static struct pci_ops bcm6328_pcie_ops = { + .read = bcm6328_pcie_read, + .write = bcm6328_pcie_write, +}; + +static struct resource bcm6328_pcie_io_resource; +static struct resource bcm6328_pcie_mem_resource; +static struct resource bcm6328_pcie_busn_resource; + +static struct pci_controller bcm6328_pcie_controller = { + .pci_ops = &bcm6328_pcie_ops, + .io_resource = &bcm6328_pcie_io_resource, + .mem_resource = &bcm6328_pcie_mem_resource, + .busn_resource = &bcm6328_pcie_busn_resource, +}; + +static void bcm6328_pcie_reset(struct bcm6328_pcie *priv) +{ + regmap_write_bits(priv->serdes, 0, + SERDES_PCIE_EXD_EN | SERDES_PCIE_EN, + SERDES_PCIE_EXD_EN | SERDES_PCIE_EN); + + reset_control_assert(priv->reset); + reset_control_assert(priv->reset_core); + reset_control_assert(priv->reset_ext); + if (priv->reset_hard) { + reset_control_assert(priv->reset_hard); + mdelay(10); + reset_control_deassert(priv->reset_hard); + } + mdelay(10); + + reset_control_deassert(priv->reset_core); + reset_control_deassert(priv->reset); + mdelay(10); + + reset_control_deassert(priv->reset_ext); + mdelay(200); +} + +static void bcm6328_pcie_setup(struct bcm6328_pcie *priv) +{ + u32 val; + + val = __raw_readl(priv->base + PCIE_BRIDGE_OPT1_REG); + val |= OPT1_RD_BE_OPT_EN; + val |= OPT1_RD_REPLY_BE_FIX_EN; + val |= OPT1_PCIE_BRIDGE_HOLE_DET_EN; + val |= OPT1_L1_INT_STATUS_MASK_POL; + __raw_writel(val, priv->base + PCIE_BRIDGE_OPT1_REG); + + val = __raw_readl(priv->base + PCIE_BRIDGE_RC_INT_MASK_REG); + val |= PCIE_RC_INT_A; + val |= PCIE_RC_INT_B; + val |= PCIE_RC_INT_C; + val |= PCIE_RC_INT_D; + __raw_writel(val, priv->base + PCIE_BRIDGE_RC_INT_MASK_REG); + + val = __raw_readl(priv->base + PCIE_BRIDGE_OPT2_REG); + /* enable credit checking and error checking */ + val |= OPT2_TX_CREDIT_CHK_EN; + val |= OPT2_UBUS_UR_DECODE_DIS; + /* set device bus/func for the pcie device */ + val |= (PCIE_BUS_DEVICE << OPT2_CFG_TYPE1_BUS_NO_SHIFT); + val |= OPT2_CFG_TYPE1_BD_SEL; + __raw_writel(val, priv->base + PCIE_BRIDGE_OPT2_REG); + + /* setup class code as bridge */ + val = __raw_readl(priv->base + PCIE_IDVAL3_REG); + val &= ~IDVAL3_CLASS_CODE_MASK; + val |= (PCI_CLASS_BRIDGE_PCI << IDVAL3_SUBCLASS_SHIFT); + __raw_writel(val, priv->base + PCIE_IDVAL3_REG); + + /* disable bar1 size */ + val = __raw_readl(priv->base + PCIE_CONFIG2_REG); + val &= ~CONFIG2_BAR1_SIZE_MASK; + __raw_writel(val, priv->base + PCIE_CONFIG2_REG); + + /* set bar0 to little endian */ + val = (bcm6328_pcie_mem_resource.start >> 20) + << BASEMASK_BASE_SHIFT; + val |= (bcm6328_pcie_mem_resource.end >> 20) << BASEMASK_MASK_SHIFT; + val |= BASEMASK_REMAP_EN; + __raw_writel(val, priv->base + PCIE_BRIDGE_BAR0_BASEMASK_REG); + + val = (bcm6328_pcie_mem_resource.start >> 20) + << REBASE_ADDR_BASE_SHIFT; + __raw_writel(val, priv->base + PCIE_BRIDGE_BAR0_REBASE_ADDR_REG); +} + +static int bcm6328_pcie_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct bcm6328_pcie *priv = &bcm6328_pcie; + struct resource *res; + unsigned int i; + int ret; + + pm_runtime_enable(dev); + pm_runtime_no_callbacks(dev); + + priv->num_pms = of_count_phandle_with_args(np, "power-domains", + "#power-domain-cells"); + if (priv->num_pms > 1) { + priv->pm = devm_kcalloc(dev, priv->num_pms, + sizeof(struct device *), GFP_KERNEL); + if (!priv->pm) + return -ENOMEM; + + priv->link_pm = devm_kcalloc(dev, priv->num_pms, + sizeof(struct device_link *), + GFP_KERNEL); + if (!priv->link_pm) + return -ENOMEM; + + for (i = 0; i < priv->num_pms; i++) { + priv->pm[i] = genpd_dev_pm_attach_by_id(dev, i); + if (IS_ERR(priv->pm[i])) { + dev_err(dev, "error getting pm %d\n", i); + return -EINVAL; + } + + priv->link_pm[i] = device_link_add(dev, priv->pm[i], + DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME | + DL_FLAG_RPM_ACTIVE); + } + } + + ret = pm_runtime_get_sync(dev); + if (ret < 0) { + pm_runtime_disable(dev); + dev_info(dev, "PM prober defer: ret=%d\n", ret); + return -EPROBE_DEFER; + } + + of_pci_check_probe_only(); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + priv->base = devm_ioremap_resource(dev, res); + if (IS_ERR(priv->base)) + return PTR_ERR(priv->base); + + priv->irq = platform_get_irq(pdev, 0); + if (!priv->irq) + return -ENODEV; + + bmips_pci_irq = priv->irq; + + priv->serdes = syscon_regmap_lookup_by_phandle(np, "brcm,serdes"); + if (IS_ERR(priv->serdes)) + return PTR_ERR(priv->serdes); + + priv->reset = devm_reset_control_get(dev, "pcie"); + if (IS_ERR(priv->reset)) + return PTR_ERR(priv->reset); + + priv->reset_ext = devm_reset_control_get(dev, "pcie-ext"); + if (IS_ERR(priv->reset_ext)) + return PTR_ERR(priv->reset_ext); + + priv->reset_core = devm_reset_control_get(dev, "pcie-core"); + if (IS_ERR(priv->reset_core)) + return PTR_ERR(priv->reset_core); + + priv->reset_hard = devm_reset_control_get_optional(dev, "pcie-hard"); + if (IS_ERR(priv->reset_hard)) + return PTR_ERR(priv->reset_hard); + + priv->clk = devm_clk_get(dev, "pcie"); + if (IS_ERR(priv->clk)) + return PTR_ERR(priv->clk); + + ret = clk_prepare_enable(priv->clk); + if (ret) { + dev_err(dev, "could not enable clock\n"); + return ret; + } + + pci_load_of_ranges(&bcm6328_pcie_controller, np); + if (!bcm6328_pcie_mem_resource.start) + return -EINVAL; + + of_pci_parse_bus_range(np, &bcm6328_pcie_busn_resource); + + bcm6328_pcie_reset(priv); + bcm6328_pcie_setup(priv); + + register_pci_controller(&bcm6328_pcie_controller); + + return 0; +} + +static const struct of_device_id bcm6328_pcie_of_match[] = { + { .compatible = "brcm,bcm6328-pcie", }, + { /* sentinel */ } +}; + +static struct platform_driver bcm6328_pcie_driver = { + .probe = bcm6328_pcie_probe, + .driver = { + .name = "bcm6328-pcie", + .of_match_table = bcm6328_pcie_of_match, + }, +}; + +int __init bcm6328_pcie_init(void) +{ + int ret = platform_driver_register(&bcm6328_pcie_driver); + if (ret) + pr_err("pci-bcm6328: Error registering platform driver!\n"); + return ret; +} +late_initcall_sync(bcm6328_pcie_init); diff --git a/target/linux/bmips/patches-5.10/600-mips-bmips-add-pci-support.patch b/target/linux/bmips/patches-5.10/600-mips-bmips-add-pci-support.patch new file mode 100644 index 0000000000..b4e7b7cfca --- /dev/null +++ b/target/linux/bmips/patches-5.10/600-mips-bmips-add-pci-support.patch @@ -0,0 +1,20 @@ +--- a/arch/mips/Kconfig ++++ b/arch/mips/Kconfig +@@ -262,6 +262,7 @@ config BMIPS_GENERIC + select BCM7038_L1_IRQ + select BCM7120_L2_IRQ + select BRCMSTB_L2_IRQ ++ select HAVE_PCI + select IRQ_MIPS_CPU + select DMA_NONCOHERENT + select SYS_SUPPORTS_32BIT_KERNEL +--- a/arch/mips/pci/Makefile ++++ b/arch/mips/pci/Makefile +@@ -28,6 +28,7 @@ obj-$(CONFIG_PCI_XTALK_BRIDGE) += pci-xt + # These are still pretty much in the old state, watch, go blind. + # + obj-$(CONFIG_ATH79) += fixup-ath79.o ++obj-$(CONFIG_BMIPS_GENERIC) += fixup-bmips.o + obj-$(CONFIG_MIPS_COBALT) += fixup-cobalt.o + obj-$(CONFIG_LEMOTE_FULOONG2E) += fixup-fuloong2e.o ops-loongson2.o + obj-$(CONFIG_LEMOTE_MACH2F) += fixup-lemote2f.o ops-loongson2.o diff --git a/target/linux/bmips/patches-5.10/601-pci-controllers-add-bcm6328-pcie-support.patch b/target/linux/bmips/patches-5.10/601-pci-controllers-add-bcm6328-pcie-support.patch new file mode 100644 index 0000000000..d7e2fe113e --- /dev/null +++ b/target/linux/bmips/patches-5.10/601-pci-controllers-add-bcm6328-pcie-support.patch @@ -0,0 +1,22 @@ +--- a/drivers/pci/controller/Kconfig ++++ b/drivers/pci/controller/Kconfig +@@ -3,6 +3,11 @@ + menu "PCI controller drivers" + depends on PCI + ++config PCIE_BCM6328 ++ bool "BCM6328 PCIe controller" ++ depends on BMIPS_GENERIC || COMPILE_TEST ++ depends on OF ++ + config PCI_MVEBU + bool "Marvell EBU PCIe controller" + depends on ARCH_MVEBU || ARCH_DOVE || COMPILE_TEST +--- a/drivers/pci/controller/Makefile ++++ b/drivers/pci/controller/Makefile +@@ -1,4 +1,5 @@ + # SPDX-License-Identifier: GPL-2.0 ++obj-$(CONFIG_PCIE_BCM6328) += pcie-bcm6328.o + obj-$(CONFIG_PCIE_CADENCE) += cadence/ + obj-$(CONFIG_PCI_FTPCI100) += pci-ftpci100.o + obj-$(CONFIG_PCI_HYPERV) += pci-hyperv.o diff --git a/target/linux/bmips/patches-5.10/602-pci-controllers-add-bcm6318-pcie-support.patch b/target/linux/bmips/patches-5.10/602-pci-controllers-add-bcm6318-pcie-support.patch new file mode 100644 index 0000000000..3674028aec --- /dev/null +++ b/target/linux/bmips/patches-5.10/602-pci-controllers-add-bcm6318-pcie-support.patch @@ -0,0 +1,22 @@ +--- a/drivers/pci/controller/Kconfig ++++ b/drivers/pci/controller/Kconfig +@@ -3,6 +3,11 @@ + menu "PCI controller drivers" + depends on PCI + ++config PCIE_BCM6318 ++ bool "BCM6318 PCIe controller" ++ depends on BMIPS_GENERIC || COMPILE_TEST ++ depends on OF ++ + config PCIE_BCM6328 + bool "BCM6328 PCIe controller" + depends on BMIPS_GENERIC || COMPILE_TEST +--- a/drivers/pci/controller/Makefile ++++ b/drivers/pci/controller/Makefile +@@ -1,4 +1,5 @@ + # SPDX-License-Identifier: GPL-2.0 ++obj-$(CONFIG_PCIE_BCM6318) += pcie-bcm6318.o + obj-$(CONFIG_PCIE_BCM6328) += pcie-bcm6328.o + obj-$(CONFIG_PCIE_CADENCE) += cadence/ + obj-$(CONFIG_PCI_FTPCI100) += pci-ftpci100.o diff --git a/target/linux/bmips/patches-5.10/603-pci-controllers-add-bcm6348-pci-support.patch b/target/linux/bmips/patches-5.10/603-pci-controllers-add-bcm6348-pci-support.patch new file mode 100644 index 0000000000..c0572604ee --- /dev/null +++ b/target/linux/bmips/patches-5.10/603-pci-controllers-add-bcm6348-pci-support.patch @@ -0,0 +1,22 @@ +--- a/drivers/pci/controller/Kconfig ++++ b/drivers/pci/controller/Kconfig +@@ -3,6 +3,11 @@ + menu "PCI controller drivers" + depends on PCI + ++config PCI_BCM6348 ++ bool "BCM6348 PCI controller" ++ depends on BMIPS_GENERIC || COMPILE_TEST ++ depends on OF ++ + config PCIE_BCM6318 + bool "BCM6318 PCIe controller" + depends on BMIPS_GENERIC || COMPILE_TEST +--- a/drivers/pci/controller/Makefile ++++ b/drivers/pci/controller/Makefile +@@ -1,4 +1,5 @@ + # SPDX-License-Identifier: GPL-2.0 ++obj-$(CONFIG_PCI_BCM6348) += pci-bcm6348.o + obj-$(CONFIG_PCIE_BCM6318) += pcie-bcm6318.o + obj-$(CONFIG_PCIE_BCM6328) += pcie-bcm6328.o + obj-$(CONFIG_PCIE_CADENCE) += cadence/ From 793047bb0f48ed61b2ea7905465ced19cda626ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Tue, 23 Mar 2021 20:14:38 +0100 Subject: [PATCH 05/31] bmips: add B43 SPROM PCI fixups MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add support for registering fallback BCMA/SSB B43 SPROMs. Signed-off-by: Álvaro Fernández Rojas --- .../bmips/dts/bcm6318-comtrend-ar-5315u.dts | 22 + .../bmips/dts/bcm6328-comtrend-ar-5387un.dts | 35 + .../bmips/dts/bcm6368-comtrend-vr-3025u.dts | 19 +- .../bmips/files/arch/mips/bmips/b43-sprom.c | 1195 +++++++++++++++++ .../610-mips-bmips-add-pci-fixups.patch | 6 + 5 files changed, 1276 insertions(+), 1 deletion(-) create mode 100644 target/linux/bmips/files/arch/mips/bmips/b43-sprom.c create mode 100644 target/linux/bmips/patches-5.10/610-mips-bmips-add-pci-fixups.patch diff --git a/target/linux/bmips/dts/bcm6318-comtrend-ar-5315u.dts b/target/linux/bmips/dts/bcm6318-comtrend-ar-5315u.dts index 5b44b05e70..725c7e38cd 100644 --- a/target/linux/bmips/dts/bcm6318-comtrend-ar-5315u.dts +++ b/target/linux/bmips/dts/bcm6318-comtrend-ar-5315u.dts @@ -31,6 +31,28 @@ debounce-interval = <60>; }; }; + + bcm43217-sprom { + compatible = "brcm,bcm43217-sprom"; + + pci-bus = <1>; + pci-dev = <0>; + + mtd-mac-address = <&cfe 0x6a0>; + mtd-mac-address-increment = <1>; + + brcm,sprom-fixups = <6 0x1c00>, + <65 0x1255>, + <97 0xfe55>, + <98 0x171d>, + <99 0xfa42>, + <113 0xfeb7>, + <114 0x18cd>, + <115 0xfa4f>, + <162 0x6444>, + <170 0x6444>, + <172 0x6444>; + }; }; &ehci { diff --git a/target/linux/bmips/dts/bcm6328-comtrend-ar-5387un.dts b/target/linux/bmips/dts/bcm6328-comtrend-ar-5387un.dts index 261162454f..14608fedb1 100644 --- a/target/linux/bmips/dts/bcm6328-comtrend-ar-5387un.dts +++ b/target/linux/bmips/dts/bcm6328-comtrend-ar-5387un.dts @@ -24,6 +24,41 @@ debounce-interval = <60>; }; }; + + bcm43225-sprom { + compatible = "brcm,bcm43225-sprom"; + + pci-bus = <1>; + pci-dev = <0>; + + mtd-mac-address = <&cfe 0x6a0>; + mtd-mac-address-increment = <1>; + + brcm,sprom-fixups = <2 0x05bb>, + <65 0x1204>, + <78 0x0303>, + <79 0x0202>, + <80 0xff02>, + <87 0x0315>, + <88 0x0315>, + <96 0x2048>, + <97 0xff11>, + <98 0x1567>, + <99 0xfb24>, + <100 0x3e3c>, + <101 0x4038>, + <102 0xfe7f>, + <103 0x1279>, + <112 0x2048>, + <113 0xff03>, + <114 0x154c>, + <115 0xfb27>, + <116 0x3e3c>, + <117 0x4038>, + <118 0xfe87>, + <119 0x1233>, + <203 0x2226>; + }; }; &ehci { diff --git a/target/linux/bmips/dts/bcm6368-comtrend-vr-3025u.dts b/target/linux/bmips/dts/bcm6368-comtrend-vr-3025u.dts index c036b1cbec..6466cb3aca 100644 --- a/target/linux/bmips/dts/bcm6368-comtrend-vr-3025u.dts +++ b/target/linux/bmips/dts/bcm6368-comtrend-vr-3025u.dts @@ -53,6 +53,23 @@ gpios = <&pinctrl 31 GPIO_ACTIVE_HIGH>; }; }; + + bcm43222-sprom { + compatible = "brcm,bcm43222-sprom"; + + pci-bus = <0>; + pci-dev = <1>; + + mtd-mac-address = <&cfe 0x6a0>; + mtd-mac-address-increment = <1>; + + brcm,sprom-fixups = <97 0xfeb3>, + <98 0x1618>, + <99 0xfab0>, + <113 0xfed1>, + <114 0x1609>, + <115 0xfad9>; + }; }; &ehci { @@ -102,7 +119,7 @@ &pinctrl { pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_pci &pinctrl_ephy0_led &pinctrl_ephy1_led + pinctrl-0 = <&pinctrl_ephy0_led &pinctrl_ephy1_led &pinctrl_ephy2_led &pinctrl_ephy3_led>; }; diff --git a/target/linux/bmips/files/arch/mips/bmips/b43-sprom.c b/target/linux/bmips/files/arch/mips/bmips/b43-sprom.c new file mode 100644 index 0000000000..2348bd1fe2 --- /dev/null +++ b/target/linux/bmips/files/arch/mips/bmips/b43-sprom.c @@ -0,0 +1,1195 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * B43 Fallback SPROM Driver + * + * Copyright (C) 2020 Álvaro Fernández Rojas + * Copyright (C) 2014 Jonas Gorski + * Copyright (C) 2008 Maxime Bizon + * Copyright (C) 2008 Florian Fainelli + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +enum b43_sprom_type { + B43_SPROM_SSB, + B43_SPROM_BCMA, + B43_SPROM_NUM +}; + +struct b43_sprom_raw { + u16 *map; + size_t size; + u8 type; +}; + +struct b43_sprom { + struct device *dev; + struct ssb_sprom sprom; + u32 pci_bus; + u32 pci_dev; + u8 mac[ETH_ALEN]; + int devid_override; +}; + +static struct b43_sprom b43_sprom; + +#if defined (CONFIG_SSB_PCIHOST) +static u16 bcm4306_sprom_map[] = { + 0x4001, 0x0000, 0x0453, 0x14e4, 0x4320, 0x8000, 0x0002, 0x0002, + 0x1000, 0x1800, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 0x0000, 0x0000, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x3034, 0x14d4, + 0xfa91, 0xfe60, 0xffff, 0xffff, 0x004c, 0xffff, 0xffff, 0xffff, + 0x003e, 0x0a49, 0xff02, 0x0000, 0xff10, 0xffff, 0xffff, 0x0002, +}; + +struct b43_sprom_raw bcm4306_sprom = { + .map = bcm4306_sprom_map, + .size = ARRAY_SIZE(bcm4306_sprom_map), + .type = B43_SPROM_SSB, +}; + +static u16 bcm4318_sprom_map[] = { + 0x2001, 0x0000, 0x0449, 0x14e4, 0x4318, 0x8000, 0x0002, 0x0000, + 0x1000, 0x1800, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 0x0000, 0x0000, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x3046, 0x15a7, + 0xfab0, 0xfe97, 0xffff, 0xffff, 0x0048, 0xffff, 0xffff, 0xffff, + 0x003e, 0xea49, 0xff02, 0x0000, 0xff08, 0xffff, 0xffff, 0x0002, +}; + +struct b43_sprom_raw bcm4318_sprom = { + .map = bcm4318_sprom_map, + .size = ARRAY_SIZE(bcm4318_sprom_map), + .type = B43_SPROM_SSB, +}; + +static u16 bcm4321_sprom_map[] = { + 0x3001, 0x0000, 0x046c, 0x14e4, 0x4328, 0x8000, 0x0002, 0x0000, + 0x1000, 0x1800, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0x5372, 0x0032, 0x4a01, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, 0x0303, 0x0202, + 0xffff, 0x2728, 0x5b5b, 0x222b, 0x5b5b, 0x1927, 0x5b5b, 0x1e36, + 0x5b5b, 0x303c, 0x3030, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0x3e4c, 0x0000, 0x0000, 0x0000, 0x0000, 0x7838, 0x3a34, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0x3e4c, + 0x0000, 0x0000, 0x0000, 0x0000, 0x7838, 0x3a34, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0x0008, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0x0004, +}; + +struct b43_sprom_raw bcm4321_sprom = { + .map = bcm4321_sprom_map, + .size = ARRAY_SIZE(bcm4321_sprom_map), + .type = B43_SPROM_SSB, +}; + +static u16 bcm4322_sprom_map[] = { + 0x3001, 0x0000, 0x04bc, 0x14e4, 0x432c, 0x8000, 0x0002, 0x0000, + 0x1730, 0x1800, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0x5372, 0x1209, 0x0200, 0x0000, 0x0400, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, 0x0303, 0x0202, + 0xffff, 0x0033, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0301, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0x2048, 0xfe9a, 0x1571, 0xfabd, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0x2048, 0xfeb9, 0x159f, 0xfadd, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x3333, 0x5555, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0x0008, +}; + +struct b43_sprom_raw bcm4322_sprom = { + .map = bcm4322_sprom_map, + .size = ARRAY_SIZE(bcm4322_sprom_map), + .type = B43_SPROM_SSB, +}; + +static u16 bcm43222_sprom_map[] = { + 0x2001, 0x0000, 0x04d4, 0x14e4, 0x4351, 0x8000, 0x0002, 0x0000, + 0x1730, 0x1800, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0x5372, 0x2305, 0x0200, 0x0000, 0x2400, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, 0x0303, 0x0202, + 0xffff, 0x0033, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0325, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0x204c, 0xfea6, 0x1717, 0xfa6d, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0x204c, 0xfeb8, 0x167c, 0xfa9e, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0x0000, 0x3333, 0x3333, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x3333, 0x3333, 0x3333, 0x3333, 0x3333, 0x3333, 0x3333, + 0x3333, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0004, 0x0000, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0x0008, +}; + +struct b43_sprom_raw bcm43222_sprom = { + .map = bcm43222_sprom_map, + .size = ARRAY_SIZE(bcm43222_sprom_map), + .type = B43_SPROM_SSB, +}; +#endif /* CONFIG_SSB_PCIHOST */ + +#if defined(CONFIG_BCMA_HOST_PCI) +static u16 bcm4313_sprom_map[] = { + 0x2801, 0x0000, 0x0510, 0x14e4, 0x0078, 0xedbe, 0x0000, 0x2bc4, + 0x2a64, 0x2964, 0x2c64, 0x3ce7, 0x46ff, 0x47ff, 0x0c00, 0x0820, + 0x0030, 0x1002, 0x9f28, 0x5d44, 0x8080, 0x1d8f, 0x0032, 0x0100, + 0xdf00, 0x71f5, 0x8400, 0x0083, 0x8500, 0x2010, 0x0001, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x1008, 0x0305, 0x0000, 0x0000, 0x0000, 0x0000, + 0x4727, 0x8000, 0x0002, 0x0000, 0x1f30, 0x1800, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x5372, 0x1215, 0x2a00, 0x0800, 0x0800, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0003, 0xffff, 0x88ff, 0xffff, 0x0003, 0x0202, + 0xffff, 0x0011, 0x007a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0201, + 0x0000, 0x7800, 0x7c0a, 0x0398, 0x0008, 0x0000, 0x0000, 0x0000, + 0x0044, 0x1684, 0xfd0d, 0xff35, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0048, 0xfed2, 0x15d9, 0xfac6, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0008, +}; + +struct b43_sprom_raw bcm4313_sprom = { + .map = bcm4313_sprom_map, + .size = ARRAY_SIZE(bcm4313_sprom_map), + .type = B43_SPROM_BCMA, +}; + +static u16 bcm4331_sprom_map[] = { + 0x2801, 0x0000, 0x0525, 0x14e4, 0x0078, 0xedbe, 0x0000, 0x2bc4, + 0x2a64, 0x2964, 0x2c64, 0x3ce7, 0x46ff, 0x47ff, 0x0c00, 0x0820, + 0x0030, 0x1002, 0x9f28, 0x5d44, 0x8080, 0x1d8f, 0x0032, 0x0100, + 0xdf00, 0x71f5, 0x8400, 0x0083, 0x8500, 0x2010, 0x0001, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0x1010, 0x0005, 0xffff, 0xffff, 0xffff, 0xffff, + 0x4331, 0x8000, 0x0002, 0x0000, 0x1f30, 0x1800, 0x0000, 0x0000, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0x5372, 0x1104, 0x0200, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xffff, 0x88ff, 0xffff, 0x0707, 0x0202, + 0xff02, 0x0077, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0325, + 0x0325, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0x2048, 0xfe56, 0x16f2, 0xfa44, 0x3e3c, 0x3c3c, 0xfe77, 0x1657, + 0xfa75, 0xffff, 0xffff, 0xffff, 0xfe76, 0x15da, 0xfa85, 0x0000, + 0x2048, 0xfe5c, 0x16b5, 0xfa56, 0x3e3c, 0x3c3c, 0xfe7c, 0x169d, + 0xfa6b, 0xffff, 0xffff, 0xffff, 0xfe7a, 0x1597, 0xfa97, 0x0000, + 0x2048, 0xfe68, 0x1734, 0xfa46, 0x3e3c, 0x3c3c, 0xfe7f, 0x15e4, + 0xfa94, 0xffff, 0xffff, 0xffff, 0xfe7d, 0x1582, 0xfa9f, 0x0000, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0x0009, +}; + +struct b43_sprom_raw bcm4331_sprom = { + .map = bcm4331_sprom_map, + .size = ARRAY_SIZE(bcm4331_sprom_map), + .type = B43_SPROM_BCMA, +}; + +static u16 bcm43131_sprom_map[] = { + 0x2801, 0x0000, 0x05f7, 0x14e4, 0x0070, 0xedbe, 0x1c00, 0x2bc4, + 0x2a64, 0x2964, 0x2c64, 0x3ce7, 0x46ff, 0x47ff, 0x0c00, 0x0820, + 0x0030, 0x1002, 0x9f28, 0x5d44, 0x8080, 0x1d8f, 0x0032, 0x0100, + 0xdf00, 0x71f5, 0x8400, 0x0083, 0x8500, 0x2010, 0x0001, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x1008, 0x0305, 0x0000, 0x0000, 0x0000, 0x0000, + 0x43aa, 0x8000, 0x0002, 0x0000, 0x1f30, 0x1800, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x5372, 0x1280, 0x0200, 0x0000, 0x8800, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0003, 0xffff, 0x88ff, 0xffff, 0x0002, 0x0202, + 0xffff, 0x0022, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0415, + 0x0000, 0x7800, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x204c, 0xfe96, 0x192c, 0xfa15, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x204c, 0xfe91, 0x1950, 0xfa0a, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0x0000, 0x4444, 0x4444, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x4444, 0x4444, 0x4444, 0x4444, 0x6666, 0x6666, 0x6666, + 0x6666, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0x0008, +}; + +struct b43_sprom_raw bcm43131_sprom = { + .map = bcm43131_sprom_map, + .size = ARRAY_SIZE(bcm43131_sprom_map), + .type = B43_SPROM_BCMA, +}; + +static u16 bcm43217_sprom_map[] = { + 0x2801, 0x0000, 0x05e9, 0x14e4, 0x0070, 0xedbe, 0x0000, 0x2bc4, + 0x2a64, 0x2964, 0x2c64, 0x3ce7, 0x46ff, 0x47ff, 0x0c00, 0x0820, + 0x0030, 0x1002, 0x9f28, 0x5d44, 0x8080, 0x1d8f, 0x0032, 0x0100, + 0xdf00, 0x71f5, 0x8400, 0x0083, 0x8500, 0x2010, 0x0001, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x1008, 0x0305, 0x0000, 0x0000, 0x0000, 0x0000, + 0x43a9, 0x8000, 0x0002, 0x0000, 0x1f30, 0x1800, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x5372, 0x1252, 0x0200, 0x0000, 0x9800, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0003, 0xffff, 0x88ff, 0xffff, 0x0003, 0x0202, + 0xffff, 0x0033, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0415, + 0x0000, 0x7800, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x204c, 0xfe96, 0x192c, 0xfa15, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x204c, 0xfe91, 0x1950, 0xfa0a, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0x0000, 0x4444, 0x4444, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x4444, 0x4444, 0x4444, 0x4444, 0x6666, 0x6666, 0x6666, + 0x6666, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0x7a08, +}; + +struct b43_sprom_raw bcm43217_sprom = { + .map = bcm43217_sprom_map, + .size = ARRAY_SIZE(bcm43217_sprom_map), + .type = B43_SPROM_BCMA, +}; + +static u16 bcm43225_sprom_map[] = { + 0x2801, 0x0000, 0x04da, 0x14e4, 0x0078, 0xedbe, 0x0000, 0x2bc4, + 0x2a64, 0x2964, 0x2c64, 0x3ce7, 0x46ff, 0x47ff, 0x0c00, 0x0820, + 0x0030, 0x1002, 0x9f28, 0x5d44, 0x8080, 0x1d8f, 0x0032, 0x0100, + 0xdf00, 0x71f5, 0x8400, 0x0083, 0x8500, 0x2010, 0x0001, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0x1008, 0x0005, 0xffff, 0xffff, 0xffff, 0xffff, + 0x4357, 0x8000, 0x0002, 0x0000, 0x1f30, 0x1800, 0x0000, 0x0000, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0x5372, 0x1200, 0x0200, 0x0000, 0x1000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x88ff, 0xffff, 0xffff, 0x0303, 0x0202, + 0xffff, 0x0033, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0325, + 0xffff, 0x7800, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0x204e, 0xfead, 0x1611, 0xfa9a, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0x204e, 0xfec1, 0x1674, 0xfab2, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0x0000, 0x5555, 0x5555, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x5555, 0x7555, 0x5555, 0x7555, 0x5555, 0x7555, 0x5555, + 0x7555, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0002, 0x0000, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0x0008, +}; + +struct b43_sprom_raw bcm43225_sprom = { + .map = bcm43225_sprom_map, + .size = ARRAY_SIZE(bcm43225_sprom_map), + .type = B43_SPROM_BCMA, +}; + +static u16 bcm43227_sprom_map[] = { + 0x2801, 0x0000, 0x0543, 0x14e4, 0x0070, 0xedbe, 0x0000, 0x2bc4, + 0x2a64, 0x2964, 0x2c64, 0x3ce7, 0x46ff, 0x47ff, 0x0c00, 0x0820, + 0x0030, 0x1002, 0x9f28, 0x5d44, 0x8080, 0x1d8f, 0x0032, 0x0100, + 0xdf00, 0x71f5, 0x8400, 0x0083, 0x8500, 0x2010, 0x0001, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x1008, 0x0305, 0x0000, 0x0000, 0x0000, 0x0000, + 0x4358, 0x8000, 0x0002, 0x0000, 0x1f30, 0x1800, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x5372, 0x1402, 0x0200, 0x0000, 0x0800, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0003, 0xffff, 0x88ff, 0xffff, 0x0003, 0x0202, + 0xffff, 0x0033, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0415, + 0x0000, 0x7800, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x204c, 0xff36, 0x16d2, 0xfaae, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x204c, 0xfeca, 0x159b, 0xfa80, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0x0000, 0x4444, 0x4444, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x4444, 0x4444, 0x4444, 0x4444, 0x6666, 0x6666, 0x6666, + 0x6666, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0x0008, +}; + +struct b43_sprom_raw bcm43227_sprom = { + .map = bcm43227_sprom_map, + .size = ARRAY_SIZE(bcm43227_sprom_map), + .type = B43_SPROM_BCMA, +}; + +static u16 bcm43228_sprom_map[] = { + 0x2801, 0x0000, 0x0011, 0x1028, 0x0070, 0xedbe, 0x0000, 0x2bc4, + 0x2a64, 0x2964, 0x2c64, 0x3ce7, 0x46ff, 0x47ff, 0x0c00, 0x0820, + 0x0030, 0x1002, 0x9f28, 0x5d44, 0x8080, 0x1d8f, 0x0032, 0x0100, + 0xdf00, 0x71f5, 0x8400, 0x0083, 0x8500, 0x2010, 0x0001, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x1008, 0x0305, 0x0000, 0x0000, 0x0000, 0x0000, + 0x4359, 0x8000, 0x0002, 0x0000, 0x1f30, 0x1800, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x5372, 0x1203, 0x0200, 0x0000, 0x0800, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0003, 0xffff, 0x88ff, 0xffff, 0x0303, 0x0202, + 0xffff, 0x0033, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0215, + 0x0215, 0x7800, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x204c, 0xff73, 0x1762, 0xfaa4, 0x3e34, 0x3434, 0xfea1, 0x154c, + 0xfad0, 0xfea1, 0x144c, 0xfafb, 0xfe7b, 0x13fe, 0xfafc, 0x0000, + 0x204c, 0xff41, 0x16a3, 0xfa8f, 0x3e34, 0x3434, 0xfe97, 0x1446, + 0xfb05, 0xfe97, 0x1346, 0xfb32, 0xfeb9, 0x1516, 0xfaee, 0x0000, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0x0000, 0x4444, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x4444, 0x4444, 0x4444, 0x4444, 0x8888, 0x8888, 0x8888, + 0x8888, 0x0000, 0x0000, 0x0000, 0x0000, 0x3333, 0x3333, 0x3333, + 0x3333, 0x0000, 0x0000, 0x0000, 0x0000, 0x3333, 0x3333, 0x3333, + 0x3333, 0x0000, 0x0000, 0x0000, 0x0000, 0x3333, 0x3333, 0x3333, + 0x3333, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xf008, +}; + +struct b43_sprom_raw bcm43228_sprom = { + .map = bcm43228_sprom_map, + .size = ARRAY_SIZE(bcm43228_sprom_map), + .type = B43_SPROM_BCMA, +}; +#endif /* CONFIG_BCMA_HOST_PCI */ + +/* Get the word-offset for a SSB_SPROM_XXX define. */ +#define SPOFF(offset) ((offset) / sizeof(u16)) +/* Helper to extract some _offset, which is one of the SSB_SPROM_XXX defines. */ +#define SPEX16(_outvar, _offset, _mask, _shift) \ + out->_outvar = ((in[SPOFF(_offset)] & (_mask)) >> (_shift)) +#define SPEX32(_outvar, _offset, _mask, _shift) \ + out->_outvar = ((((u32)in[SPOFF((_offset)+2)] << 16 | \ + in[SPOFF(_offset)]) & (_mask)) >> (_shift)) +#define SPEX(_outvar, _offset, _mask, _shift) \ + SPEX16(_outvar, _offset, _mask, _shift) + +#define SPEX_ARRAY8(_field, _offset, _mask, _shift) \ + do { \ + SPEX(_field[0], _offset + 0, _mask, _shift); \ + SPEX(_field[1], _offset + 2, _mask, _shift); \ + SPEX(_field[2], _offset + 4, _mask, _shift); \ + SPEX(_field[3], _offset + 6, _mask, _shift); \ + SPEX(_field[4], _offset + 8, _mask, _shift); \ + SPEX(_field[5], _offset + 10, _mask, _shift); \ + SPEX(_field[6], _offset + 12, _mask, _shift); \ + SPEX(_field[7], _offset + 14, _mask, _shift); \ + } while (0) + + +static s8 sprom_extract_antgain(u8 sprom_revision, const u16 *in, u16 offset, + u16 mask, u16 shift) +{ + u16 v; + u8 gain; + + v = in[SPOFF(offset)]; + gain = (v & mask) >> shift; + if (gain == 0xFF) + gain = 2; /* If unset use 2dBm */ + if (sprom_revision == 1) { + /* Convert to Q5.2 */ + gain <<= 2; + } else { + /* Q5.2 Fractional part is stored in 0xC0 */ + gain = ((gain & 0xC0) >> 6) | ((gain & 0x3F) << 2); + } + + return (s8)gain; +} + +static void sprom_extract_r23(struct ssb_sprom *out, const u16 *in) +{ + SPEX(boardflags_hi, SSB_SPROM2_BFLHI, 0xFFFF, 0); + SPEX(opo, SSB_SPROM2_OPO, SSB_SPROM2_OPO_VALUE, 0); + SPEX(pa1lob0, SSB_SPROM2_PA1LOB0, 0xFFFF, 0); + SPEX(pa1lob1, SSB_SPROM2_PA1LOB1, 0xFFFF, 0); + SPEX(pa1lob2, SSB_SPROM2_PA1LOB2, 0xFFFF, 0); + SPEX(pa1hib0, SSB_SPROM2_PA1HIB0, 0xFFFF, 0); + SPEX(pa1hib1, SSB_SPROM2_PA1HIB1, 0xFFFF, 0); + SPEX(pa1hib2, SSB_SPROM2_PA1HIB2, 0xFFFF, 0); + SPEX(maxpwr_ah, SSB_SPROM2_MAXP_A, SSB_SPROM2_MAXP_A_HI, 0); + SPEX(maxpwr_al, SSB_SPROM2_MAXP_A, SSB_SPROM2_MAXP_A_LO, + SSB_SPROM2_MAXP_A_LO_SHIFT); +} + +static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in) +{ + u16 loc[3]; + + if (out->revision == 3) /* rev 3 moved MAC */ + loc[0] = SSB_SPROM3_IL0MAC; + else { + loc[0] = SSB_SPROM1_IL0MAC; + loc[1] = SSB_SPROM1_ET0MAC; + loc[2] = SSB_SPROM1_ET1MAC; + } + + SPEX(et0phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0A, 0); + SPEX(et1phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1A, + SSB_SPROM1_ETHPHY_ET1A_SHIFT); + SPEX(et0mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0M, 14); + SPEX(et1mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1M, 15); + SPEX(board_rev, SSB_SPROM1_BINF, SSB_SPROM1_BINF_BREV, 0); + SPEX(board_type, SSB_SPROM1_SPID, 0xFFFF, 0); + if (out->revision == 1) + SPEX(country_code, SSB_SPROM1_BINF, SSB_SPROM1_BINF_CCODE, + SSB_SPROM1_BINF_CCODE_SHIFT); + SPEX(ant_available_a, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTA, + SSB_SPROM1_BINF_ANTA_SHIFT); + SPEX(ant_available_bg, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTBG, + SSB_SPROM1_BINF_ANTBG_SHIFT); + SPEX(pa0b0, SSB_SPROM1_PA0B0, 0xFFFF, 0); + SPEX(pa0b1, SSB_SPROM1_PA0B1, 0xFFFF, 0); + SPEX(pa0b2, SSB_SPROM1_PA0B2, 0xFFFF, 0); + SPEX(pa1b0, SSB_SPROM1_PA1B0, 0xFFFF, 0); + SPEX(pa1b1, SSB_SPROM1_PA1B1, 0xFFFF, 0); + SPEX(pa1b2, SSB_SPROM1_PA1B2, 0xFFFF, 0); + SPEX(gpio0, SSB_SPROM1_GPIOA, SSB_SPROM1_GPIOA_P0, 0); + SPEX(gpio1, SSB_SPROM1_GPIOA, SSB_SPROM1_GPIOA_P1, + SSB_SPROM1_GPIOA_P1_SHIFT); + SPEX(gpio2, SSB_SPROM1_GPIOB, SSB_SPROM1_GPIOB_P2, 0); + SPEX(gpio3, SSB_SPROM1_GPIOB, SSB_SPROM1_GPIOB_P3, + SSB_SPROM1_GPIOB_P3_SHIFT); + SPEX(maxpwr_a, SSB_SPROM1_MAXPWR, SSB_SPROM1_MAXPWR_A, + SSB_SPROM1_MAXPWR_A_SHIFT); + SPEX(maxpwr_bg, SSB_SPROM1_MAXPWR, SSB_SPROM1_MAXPWR_BG, 0); + SPEX(itssi_a, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_A, + SSB_SPROM1_ITSSI_A_SHIFT); + SPEX(itssi_bg, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_BG, 0); + SPEX(boardflags_lo, SSB_SPROM1_BFLLO, 0xFFFF, 0); + + SPEX(alpha2[0], SSB_SPROM1_CCODE, 0xff00, 8); + SPEX(alpha2[1], SSB_SPROM1_CCODE, 0x00ff, 0); + + /* Extract the antenna gain values. */ + out->antenna_gain.a0 = sprom_extract_antgain(out->revision, in, + SSB_SPROM1_AGAIN, + SSB_SPROM1_AGAIN_BG, + SSB_SPROM1_AGAIN_BG_SHIFT); + out->antenna_gain.a1 = sprom_extract_antgain(out->revision, in, + SSB_SPROM1_AGAIN, + SSB_SPROM1_AGAIN_A, + SSB_SPROM1_AGAIN_A_SHIFT); + if (out->revision >= 2) + sprom_extract_r23(out, in); +} + +/* Revs 4 5 and 8 have partially shared layout */ +static void sprom_extract_r458(struct ssb_sprom *out, const u16 *in) +{ + SPEX(txpid2g[0], SSB_SPROM4_TXPID2G01, + SSB_SPROM4_TXPID2G0, SSB_SPROM4_TXPID2G0_SHIFT); + SPEX(txpid2g[1], SSB_SPROM4_TXPID2G01, + SSB_SPROM4_TXPID2G1, SSB_SPROM4_TXPID2G1_SHIFT); + SPEX(txpid2g[2], SSB_SPROM4_TXPID2G23, + SSB_SPROM4_TXPID2G2, SSB_SPROM4_TXPID2G2_SHIFT); + SPEX(txpid2g[3], SSB_SPROM4_TXPID2G23, + SSB_SPROM4_TXPID2G3, SSB_SPROM4_TXPID2G3_SHIFT); + + SPEX(txpid5gl[0], SSB_SPROM4_TXPID5GL01, + SSB_SPROM4_TXPID5GL0, SSB_SPROM4_TXPID5GL0_SHIFT); + SPEX(txpid5gl[1], SSB_SPROM4_TXPID5GL01, + SSB_SPROM4_TXPID5GL1, SSB_SPROM4_TXPID5GL1_SHIFT); + SPEX(txpid5gl[2], SSB_SPROM4_TXPID5GL23, + SSB_SPROM4_TXPID5GL2, SSB_SPROM4_TXPID5GL2_SHIFT); + SPEX(txpid5gl[3], SSB_SPROM4_TXPID5GL23, + SSB_SPROM4_TXPID5GL3, SSB_SPROM4_TXPID5GL3_SHIFT); + + SPEX(txpid5g[0], SSB_SPROM4_TXPID5G01, + SSB_SPROM4_TXPID5G0, SSB_SPROM4_TXPID5G0_SHIFT); + SPEX(txpid5g[1], SSB_SPROM4_TXPID5G01, + SSB_SPROM4_TXPID5G1, SSB_SPROM4_TXPID5G1_SHIFT); + SPEX(txpid5g[2], SSB_SPROM4_TXPID5G23, + SSB_SPROM4_TXPID5G2, SSB_SPROM4_TXPID5G2_SHIFT); + SPEX(txpid5g[3], SSB_SPROM4_TXPID5G23, + SSB_SPROM4_TXPID5G3, SSB_SPROM4_TXPID5G3_SHIFT); + + SPEX(txpid5gh[0], SSB_SPROM4_TXPID5GH01, + SSB_SPROM4_TXPID5GH0, SSB_SPROM4_TXPID5GH0_SHIFT); + SPEX(txpid5gh[1], SSB_SPROM4_TXPID5GH01, + SSB_SPROM4_TXPID5GH1, SSB_SPROM4_TXPID5GH1_SHIFT); + SPEX(txpid5gh[2], SSB_SPROM4_TXPID5GH23, + SSB_SPROM4_TXPID5GH2, SSB_SPROM4_TXPID5GH2_SHIFT); + SPEX(txpid5gh[3], SSB_SPROM4_TXPID5GH23, + SSB_SPROM4_TXPID5GH3, SSB_SPROM4_TXPID5GH3_SHIFT); +} + +static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in) +{ + static const u16 pwr_info_offset[] = { + SSB_SPROM4_PWR_INFO_CORE0, SSB_SPROM4_PWR_INFO_CORE1, + SSB_SPROM4_PWR_INFO_CORE2, SSB_SPROM4_PWR_INFO_CORE3 + }; + int i; + + BUILD_BUG_ON(ARRAY_SIZE(pwr_info_offset) != + ARRAY_SIZE(out->core_pwr_info)); + + SPEX(et0phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET0A, 0); + SPEX(et1phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET1A, + SSB_SPROM4_ETHPHY_ET1A_SHIFT); + SPEX(board_rev, SSB_SPROM4_BOARDREV, 0xFFFF, 0); + SPEX(board_type, SSB_SPROM1_SPID, 0xFFFF, 0); + if (out->revision == 4) { + SPEX(alpha2[0], SSB_SPROM4_CCODE, 0xff00, 8); + SPEX(alpha2[1], SSB_SPROM4_CCODE, 0x00ff, 0); + SPEX(boardflags_lo, SSB_SPROM4_BFLLO, 0xFFFF, 0); + SPEX(boardflags_hi, SSB_SPROM4_BFLHI, 0xFFFF, 0); + SPEX(boardflags2_lo, SSB_SPROM4_BFL2LO, 0xFFFF, 0); + SPEX(boardflags2_hi, SSB_SPROM4_BFL2HI, 0xFFFF, 0); + } else { + SPEX(alpha2[0], SSB_SPROM5_CCODE, 0xff00, 8); + SPEX(alpha2[1], SSB_SPROM5_CCODE, 0x00ff, 0); + SPEX(boardflags_lo, SSB_SPROM5_BFLLO, 0xFFFF, 0); + SPEX(boardflags_hi, SSB_SPROM5_BFLHI, 0xFFFF, 0); + SPEX(boardflags2_lo, SSB_SPROM5_BFL2LO, 0xFFFF, 0); + SPEX(boardflags2_hi, SSB_SPROM5_BFL2HI, 0xFFFF, 0); + } + SPEX(ant_available_a, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_A, + SSB_SPROM4_ANTAVAIL_A_SHIFT); + SPEX(ant_available_bg, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_BG, + SSB_SPROM4_ANTAVAIL_BG_SHIFT); + SPEX(maxpwr_bg, SSB_SPROM4_MAXP_BG, SSB_SPROM4_MAXP_BG_MASK, 0); + SPEX(itssi_bg, SSB_SPROM4_MAXP_BG, SSB_SPROM4_ITSSI_BG, + SSB_SPROM4_ITSSI_BG_SHIFT); + SPEX(maxpwr_a, SSB_SPROM4_MAXP_A, SSB_SPROM4_MAXP_A_MASK, 0); + SPEX(itssi_a, SSB_SPROM4_MAXP_A, SSB_SPROM4_ITSSI_A, + SSB_SPROM4_ITSSI_A_SHIFT); + if (out->revision == 4) { + SPEX(gpio0, SSB_SPROM4_GPIOA, SSB_SPROM4_GPIOA_P0, 0); + SPEX(gpio1, SSB_SPROM4_GPIOA, SSB_SPROM4_GPIOA_P1, + SSB_SPROM4_GPIOA_P1_SHIFT); + SPEX(gpio2, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P2, 0); + SPEX(gpio3, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P3, + SSB_SPROM4_GPIOB_P3_SHIFT); + } else { + SPEX(gpio0, SSB_SPROM5_GPIOA, SSB_SPROM5_GPIOA_P0, 0); + SPEX(gpio1, SSB_SPROM5_GPIOA, SSB_SPROM5_GPIOA_P1, + SSB_SPROM5_GPIOA_P1_SHIFT); + SPEX(gpio2, SSB_SPROM5_GPIOB, SSB_SPROM5_GPIOB_P2, 0); + SPEX(gpio3, SSB_SPROM5_GPIOB, SSB_SPROM5_GPIOB_P3, + SSB_SPROM5_GPIOB_P3_SHIFT); + } + + /* Extract the antenna gain values. */ + out->antenna_gain.a0 = sprom_extract_antgain(out->revision, in, + SSB_SPROM4_AGAIN01, + SSB_SPROM4_AGAIN0, + SSB_SPROM4_AGAIN0_SHIFT); + out->antenna_gain.a1 = sprom_extract_antgain(out->revision, in, + SSB_SPROM4_AGAIN01, + SSB_SPROM4_AGAIN1, + SSB_SPROM4_AGAIN1_SHIFT); + out->antenna_gain.a2 = sprom_extract_antgain(out->revision, in, + SSB_SPROM4_AGAIN23, + SSB_SPROM4_AGAIN2, + SSB_SPROM4_AGAIN2_SHIFT); + out->antenna_gain.a3 = sprom_extract_antgain(out->revision, in, + SSB_SPROM4_AGAIN23, + SSB_SPROM4_AGAIN3, + SSB_SPROM4_AGAIN3_SHIFT); + + /* Extract cores power info info */ + for (i = 0; i < ARRAY_SIZE(pwr_info_offset); i++) { + u16 o = pwr_info_offset[i]; + + SPEX(core_pwr_info[i].itssi_2g, o + SSB_SPROM4_2G_MAXP_ITSSI, + SSB_SPROM4_2G_ITSSI, SSB_SPROM4_2G_ITSSI_SHIFT); + SPEX(core_pwr_info[i].maxpwr_2g, o + SSB_SPROM4_2G_MAXP_ITSSI, + SSB_SPROM4_2G_MAXP, 0); + + SPEX(core_pwr_info[i].pa_2g[0], o + SSB_SPROM4_2G_PA_0, ~0, 0); + SPEX(core_pwr_info[i].pa_2g[1], o + SSB_SPROM4_2G_PA_1, ~0, 0); + SPEX(core_pwr_info[i].pa_2g[2], o + SSB_SPROM4_2G_PA_2, ~0, 0); + SPEX(core_pwr_info[i].pa_2g[3], o + SSB_SPROM4_2G_PA_3, ~0, 0); + + SPEX(core_pwr_info[i].itssi_5g, o + SSB_SPROM4_5G_MAXP_ITSSI, + SSB_SPROM4_5G_ITSSI, SSB_SPROM4_5G_ITSSI_SHIFT); + SPEX(core_pwr_info[i].maxpwr_5g, o + SSB_SPROM4_5G_MAXP_ITSSI, + SSB_SPROM4_5G_MAXP, 0); + SPEX(core_pwr_info[i].maxpwr_5gh, o + SSB_SPROM4_5GHL_MAXP, + SSB_SPROM4_5GH_MAXP, 0); + SPEX(core_pwr_info[i].maxpwr_5gl, o + SSB_SPROM4_5GHL_MAXP, + SSB_SPROM4_5GL_MAXP, SSB_SPROM4_5GL_MAXP_SHIFT); + + SPEX(core_pwr_info[i].pa_5gl[0], o + SSB_SPROM4_5GL_PA_0, ~0, 0); + SPEX(core_pwr_info[i].pa_5gl[1], o + SSB_SPROM4_5GL_PA_1, ~0, 0); + SPEX(core_pwr_info[i].pa_5gl[2], o + SSB_SPROM4_5GL_PA_2, ~0, 0); + SPEX(core_pwr_info[i].pa_5gl[3], o + SSB_SPROM4_5GL_PA_3, ~0, 0); + SPEX(core_pwr_info[i].pa_5g[0], o + SSB_SPROM4_5G_PA_0, ~0, 0); + SPEX(core_pwr_info[i].pa_5g[1], o + SSB_SPROM4_5G_PA_1, ~0, 0); + SPEX(core_pwr_info[i].pa_5g[2], o + SSB_SPROM4_5G_PA_2, ~0, 0); + SPEX(core_pwr_info[i].pa_5g[3], o + SSB_SPROM4_5G_PA_3, ~0, 0); + SPEX(core_pwr_info[i].pa_5gh[0], o + SSB_SPROM4_5GH_PA_0, ~0, 0); + SPEX(core_pwr_info[i].pa_5gh[1], o + SSB_SPROM4_5GH_PA_1, ~0, 0); + SPEX(core_pwr_info[i].pa_5gh[2], o + SSB_SPROM4_5GH_PA_2, ~0, 0); + SPEX(core_pwr_info[i].pa_5gh[3], o + SSB_SPROM4_5GH_PA_3, ~0, 0); + } + + sprom_extract_r458(out, in); + + /* TODO - get remaining rev 4 stuff needed */ +} + +static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in) +{ + int i; + u16 o; + static const u16 pwr_info_offset[] = { + SSB_SROM8_PWR_INFO_CORE0, SSB_SROM8_PWR_INFO_CORE1, + SSB_SROM8_PWR_INFO_CORE2, SSB_SROM8_PWR_INFO_CORE3 + }; + BUILD_BUG_ON(ARRAY_SIZE(pwr_info_offset) != + ARRAY_SIZE(out->core_pwr_info)); + + SPEX(board_rev, SSB_SPROM8_BOARDREV, 0xFFFF, 0); + SPEX(board_type, SSB_SPROM1_SPID, 0xFFFF, 0); + SPEX(alpha2[0], SSB_SPROM8_CCODE, 0xff00, 8); + SPEX(alpha2[1], SSB_SPROM8_CCODE, 0x00ff, 0); + SPEX(boardflags_lo, SSB_SPROM8_BFLLO, 0xFFFF, 0); + SPEX(boardflags_hi, SSB_SPROM8_BFLHI, 0xFFFF, 0); + SPEX(boardflags2_lo, SSB_SPROM8_BFL2LO, 0xFFFF, 0); + SPEX(boardflags2_hi, SSB_SPROM8_BFL2HI, 0xFFFF, 0); + SPEX(ant_available_a, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_A, + SSB_SPROM8_ANTAVAIL_A_SHIFT); + SPEX(ant_available_bg, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_BG, + SSB_SPROM8_ANTAVAIL_BG_SHIFT); + SPEX(maxpwr_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_MAXP_BG_MASK, 0); + SPEX(itssi_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_ITSSI_BG, + SSB_SPROM8_ITSSI_BG_SHIFT); + SPEX(maxpwr_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_MAXP_A_MASK, 0); + SPEX(itssi_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_ITSSI_A, + SSB_SPROM8_ITSSI_A_SHIFT); + SPEX(maxpwr_ah, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AH_MASK, 0); + SPEX(maxpwr_al, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AL_MASK, + SSB_SPROM8_MAXP_AL_SHIFT); + SPEX(gpio0, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P0, 0); + SPEX(gpio1, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P1, + SSB_SPROM8_GPIOA_P1_SHIFT); + SPEX(gpio2, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P2, 0); + SPEX(gpio3, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P3, + SSB_SPROM8_GPIOB_P3_SHIFT); + SPEX(tri2g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI2G, 0); + SPEX(tri5g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI5G, + SSB_SPROM8_TRI5G_SHIFT); + SPEX(tri5gl, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GL, 0); + SPEX(tri5gh, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GH, + SSB_SPROM8_TRI5GH_SHIFT); + SPEX(rxpo2g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO2G, 0); + SPEX(rxpo5g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO5G, + SSB_SPROM8_RXPO5G_SHIFT); + SPEX(rssismf2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMF2G, 0); + SPEX(rssismc2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMC2G, + SSB_SPROM8_RSSISMC2G_SHIFT); + SPEX(rssisav2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISAV2G, + SSB_SPROM8_RSSISAV2G_SHIFT); + SPEX(bxa2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_BXA2G, + SSB_SPROM8_BXA2G_SHIFT); + SPEX(rssismf5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMF5G, 0); + SPEX(rssismc5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMC5G, + SSB_SPROM8_RSSISMC5G_SHIFT); + SPEX(rssisav5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISAV5G, + SSB_SPROM8_RSSISAV5G_SHIFT); + SPEX(bxa5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_BXA5G, + SSB_SPROM8_BXA5G_SHIFT); + SPEX(pa0b0, SSB_SPROM8_PA0B0, 0xFFFF, 0); + SPEX(pa0b1, SSB_SPROM8_PA0B1, 0xFFFF, 0); + SPEX(pa0b2, SSB_SPROM8_PA0B2, 0xFFFF, 0); + SPEX(pa1b0, SSB_SPROM8_PA1B0, 0xFFFF, 0); + SPEX(pa1b1, SSB_SPROM8_PA1B1, 0xFFFF, 0); + SPEX(pa1b2, SSB_SPROM8_PA1B2, 0xFFFF, 0); + SPEX(pa1lob0, SSB_SPROM8_PA1LOB0, 0xFFFF, 0); + SPEX(pa1lob1, SSB_SPROM8_PA1LOB1, 0xFFFF, 0); + SPEX(pa1lob2, SSB_SPROM8_PA1LOB2, 0xFFFF, 0); + SPEX(pa1hib0, SSB_SPROM8_PA1HIB0, 0xFFFF, 0); + SPEX(pa1hib1, SSB_SPROM8_PA1HIB1, 0xFFFF, 0); + SPEX(pa1hib2, SSB_SPROM8_PA1HIB2, 0xFFFF, 0); + SPEX(cck2gpo, SSB_SPROM8_CCK2GPO, 0xFFFF, 0); + SPEX32(ofdm2gpo, SSB_SPROM8_OFDM2GPO, 0xFFFFFFFF, 0); + SPEX32(ofdm5glpo, SSB_SPROM8_OFDM5GLPO, 0xFFFFFFFF, 0); + SPEX32(ofdm5gpo, SSB_SPROM8_OFDM5GPO, 0xFFFFFFFF, 0); + SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, 0xFFFFFFFF, 0); + + /* Extract the antenna gain values. */ + out->antenna_gain.a0 = sprom_extract_antgain(out->revision, in, + SSB_SPROM8_AGAIN01, + SSB_SPROM8_AGAIN0, + SSB_SPROM8_AGAIN0_SHIFT); + out->antenna_gain.a1 = sprom_extract_antgain(out->revision, in, + SSB_SPROM8_AGAIN01, + SSB_SPROM8_AGAIN1, + SSB_SPROM8_AGAIN1_SHIFT); + out->antenna_gain.a2 = sprom_extract_antgain(out->revision, in, + SSB_SPROM8_AGAIN23, + SSB_SPROM8_AGAIN2, + SSB_SPROM8_AGAIN2_SHIFT); + out->antenna_gain.a3 = sprom_extract_antgain(out->revision, in, + SSB_SPROM8_AGAIN23, + SSB_SPROM8_AGAIN3, + SSB_SPROM8_AGAIN3_SHIFT); + + /* Extract cores power info info */ + for (i = 0; i < ARRAY_SIZE(pwr_info_offset); i++) { + o = pwr_info_offset[i]; + SPEX(core_pwr_info[i].itssi_2g, o + SSB_SROM8_2G_MAXP_ITSSI, + SSB_SPROM8_2G_ITSSI, SSB_SPROM8_2G_ITSSI_SHIFT); + SPEX(core_pwr_info[i].maxpwr_2g, o + SSB_SROM8_2G_MAXP_ITSSI, + SSB_SPROM8_2G_MAXP, 0); + + SPEX(core_pwr_info[i].pa_2g[0], o + SSB_SROM8_2G_PA_0, ~0, 0); + SPEX(core_pwr_info[i].pa_2g[1], o + SSB_SROM8_2G_PA_1, ~0, 0); + SPEX(core_pwr_info[i].pa_2g[2], o + SSB_SROM8_2G_PA_2, ~0, 0); + + SPEX(core_pwr_info[i].itssi_5g, o + SSB_SROM8_5G_MAXP_ITSSI, + SSB_SPROM8_5G_ITSSI, SSB_SPROM8_5G_ITSSI_SHIFT); + SPEX(core_pwr_info[i].maxpwr_5g, o + SSB_SROM8_5G_MAXP_ITSSI, + SSB_SPROM8_5G_MAXP, 0); + SPEX(core_pwr_info[i].maxpwr_5gh, o + SSB_SPROM8_5GHL_MAXP, + SSB_SPROM8_5GH_MAXP, 0); + SPEX(core_pwr_info[i].maxpwr_5gl, o + SSB_SPROM8_5GHL_MAXP, + SSB_SPROM8_5GL_MAXP, SSB_SPROM8_5GL_MAXP_SHIFT); + + SPEX(core_pwr_info[i].pa_5gl[0], o + SSB_SROM8_5GL_PA_0, ~0, 0); + SPEX(core_pwr_info[i].pa_5gl[1], o + SSB_SROM8_5GL_PA_1, ~0, 0); + SPEX(core_pwr_info[i].pa_5gl[2], o + SSB_SROM8_5GL_PA_2, ~0, 0); + SPEX(core_pwr_info[i].pa_5g[0], o + SSB_SROM8_5G_PA_0, ~0, 0); + SPEX(core_pwr_info[i].pa_5g[1], o + SSB_SROM8_5G_PA_1, ~0, 0); + SPEX(core_pwr_info[i].pa_5g[2], o + SSB_SROM8_5G_PA_2, ~0, 0); + SPEX(core_pwr_info[i].pa_5gh[0], o + SSB_SROM8_5GH_PA_0, ~0, 0); + SPEX(core_pwr_info[i].pa_5gh[1], o + SSB_SROM8_5GH_PA_1, ~0, 0); + SPEX(core_pwr_info[i].pa_5gh[2], o + SSB_SROM8_5GH_PA_2, ~0, 0); + } + + /* Extract FEM info */ + SPEX(fem.ghz2.tssipos, SSB_SPROM8_FEM2G, + SSB_SROM8_FEM_TSSIPOS, SSB_SROM8_FEM_TSSIPOS_SHIFT); + SPEX(fem.ghz2.extpa_gain, SSB_SPROM8_FEM2G, + SSB_SROM8_FEM_EXTPA_GAIN, SSB_SROM8_FEM_EXTPA_GAIN_SHIFT); + SPEX(fem.ghz2.pdet_range, SSB_SPROM8_FEM2G, + SSB_SROM8_FEM_PDET_RANGE, SSB_SROM8_FEM_PDET_RANGE_SHIFT); + SPEX(fem.ghz2.tr_iso, SSB_SPROM8_FEM2G, + SSB_SROM8_FEM_TR_ISO, SSB_SROM8_FEM_TR_ISO_SHIFT); + SPEX(fem.ghz2.antswlut, SSB_SPROM8_FEM2G, + SSB_SROM8_FEM_ANTSWLUT, SSB_SROM8_FEM_ANTSWLUT_SHIFT); + + SPEX(fem.ghz5.tssipos, SSB_SPROM8_FEM5G, + SSB_SROM8_FEM_TSSIPOS, SSB_SROM8_FEM_TSSIPOS_SHIFT); + SPEX(fem.ghz5.extpa_gain, SSB_SPROM8_FEM5G, + SSB_SROM8_FEM_EXTPA_GAIN, SSB_SROM8_FEM_EXTPA_GAIN_SHIFT); + SPEX(fem.ghz5.pdet_range, SSB_SPROM8_FEM5G, + SSB_SROM8_FEM_PDET_RANGE, SSB_SROM8_FEM_PDET_RANGE_SHIFT); + SPEX(fem.ghz5.tr_iso, SSB_SPROM8_FEM5G, + SSB_SROM8_FEM_TR_ISO, SSB_SROM8_FEM_TR_ISO_SHIFT); + SPEX(fem.ghz5.antswlut, SSB_SPROM8_FEM5G, + SSB_SROM8_FEM_ANTSWLUT, SSB_SROM8_FEM_ANTSWLUT_SHIFT); + + SPEX(leddc_on_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_ON, + SSB_SPROM8_LEDDC_ON_SHIFT); + SPEX(leddc_off_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_OFF, + SSB_SPROM8_LEDDC_OFF_SHIFT); + + SPEX(txchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_TXCHAIN, + SSB_SPROM8_TXRXC_TXCHAIN_SHIFT); + SPEX(rxchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_RXCHAIN, + SSB_SPROM8_TXRXC_RXCHAIN_SHIFT); + SPEX(antswitch, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_SWITCH, + SSB_SPROM8_TXRXC_SWITCH_SHIFT); + + SPEX(opo, SSB_SPROM8_OFDM2GPO, 0x00ff, 0); + + SPEX_ARRAY8(mcs2gpo, SSB_SPROM8_2G_MCSPO, ~0, 0); + SPEX_ARRAY8(mcs5gpo, SSB_SPROM8_5G_MCSPO, ~0, 0); + SPEX_ARRAY8(mcs5glpo, SSB_SPROM8_5GL_MCSPO, ~0, 0); + SPEX_ARRAY8(mcs5ghpo, SSB_SPROM8_5GH_MCSPO, ~0, 0); + + SPEX(rawtempsense, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_RAWTEMP, + SSB_SPROM8_RAWTS_RAWTEMP_SHIFT); + SPEX(measpower, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_MEASPOWER, + SSB_SPROM8_RAWTS_MEASPOWER_SHIFT); + SPEX(tempsense_slope, SSB_SPROM8_OPT_CORRX, + SSB_SPROM8_OPT_CORRX_TEMP_SLOPE, + SSB_SPROM8_OPT_CORRX_TEMP_SLOPE_SHIFT); + SPEX(tempcorrx, SSB_SPROM8_OPT_CORRX, SSB_SPROM8_OPT_CORRX_TEMPCORRX, + SSB_SPROM8_OPT_CORRX_TEMPCORRX_SHIFT); + SPEX(tempsense_option, SSB_SPROM8_OPT_CORRX, + SSB_SPROM8_OPT_CORRX_TEMP_OPTION, + SSB_SPROM8_OPT_CORRX_TEMP_OPTION_SHIFT); + SPEX(freqoffset_corr, SSB_SPROM8_HWIQ_IQSWP, + SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR, + SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR_SHIFT); + SPEX(iqcal_swp_dis, SSB_SPROM8_HWIQ_IQSWP, + SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP, + SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP_SHIFT); + SPEX(hw_iqcal_en, SSB_SPROM8_HWIQ_IQSWP, SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL, + SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL_SHIFT); + + SPEX(bw40po, SSB_SPROM8_BW40PO, ~0, 0); + SPEX(cddpo, SSB_SPROM8_CDDPO, ~0, 0); + SPEX(stbcpo, SSB_SPROM8_STBCPO, ~0, 0); + SPEX(bwduppo, SSB_SPROM8_BWDUPPO, ~0, 0); + + SPEX(tempthresh, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_TRESH, + SSB_SPROM8_THERMAL_TRESH_SHIFT); + SPEX(tempoffset, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_OFFSET, + SSB_SPROM8_THERMAL_OFFSET_SHIFT); + SPEX(phycal_tempdelta, SSB_SPROM8_TEMPDELTA, + SSB_SPROM8_TEMPDELTA_PHYCAL, + SSB_SPROM8_TEMPDELTA_PHYCAL_SHIFT); + SPEX(temps_period, SSB_SPROM8_TEMPDELTA, SSB_SPROM8_TEMPDELTA_PERIOD, + SSB_SPROM8_TEMPDELTA_PERIOD_SHIFT); + SPEX(temps_hysteresis, SSB_SPROM8_TEMPDELTA, + SSB_SPROM8_TEMPDELTA_HYSTERESIS, + SSB_SPROM8_TEMPDELTA_HYSTERESIS_SHIFT); + sprom_extract_r458(out, in); + + /* TODO - get remaining rev 8 stuff needed */ +} + +static int sprom_extract(struct ssb_sprom *out, const u16 *in, u16 size) +{ + memset(out, 0, sizeof(*out)); + + out->revision = in[size - 1] & 0x00FF; + memset(out->et0mac, 0xFF, 6); /* preset et0 and et1 mac */ + memset(out->et1mac, 0xFF, 6); + + switch (out->revision) { + case 1: + case 2: + case 3: + sprom_extract_r123(out, in); + break; + case 4: + case 5: + sprom_extract_r45(out, in); + break; + case 8: + sprom_extract_r8(out, in); + break; + default: + pr_warn("Unsupported SPROM revision %d detected. Will extract v1\n", + out->revision); + out->revision = 1; + sprom_extract_r123(out, in); + } + + if (out->boardflags_lo == 0xFFFF) + out->boardflags_lo = 0; /* per specs */ + if (out->boardflags_hi == 0xFFFF) + out->boardflags_hi = 0; /* per specs */ + + return 0; +} + +static void b43_sprom_fixup(struct b43_sprom *priv, u16 *sprom) +{ + struct device_node *node = priv->dev->of_node; + u32 fixups, off, val; + int i = 0; + + if (!of_get_property(node, "brcm,sprom-fixups", &fixups)) + return; + + fixups /= sizeof(u32); + + dev_info(priv->dev, "patching SPROM with %u fixups...\n", fixups >> 1); + + while (i < fixups) { + if (of_property_read_u32_index(node, "brcm,sprom-fixups", + i++, &off)) { + dev_err(priv->dev, "error reading fixup[%u] offset\n", + i - 1); + return; + } + + if (of_property_read_u32_index(node, "brcm,sprom-fixups", + i++, &val)) { + dev_err(priv->dev, "error reading fixup[%u] value\n", + i - 1); + return; + } + + dev_dbg(priv->dev, "fixup[%d]=0x%04x\n", off, val); + + sprom[off] = val; + } +} + +int sprom_override_devid(struct b43_sprom *priv, struct ssb_sprom *out, + const u16 *in) +{ + const struct b43_sprom_raw *raw = of_device_get_match_data(priv->dev); + + if (raw->type == B43_SPROM_SSB) { + SPEX(dev_id, SSB_SPROM1_PID, 0xFFFF, 0); + return !!out->dev_id; + } else if (raw->type == B43_SPROM_BCMA) { + SPEX(dev_id, 0x0060, 0xFFFF, 0); + return !!out->dev_id; + } + + return 0; +} + +static void b43_sprom_set(struct b43_sprom *priv) +{ + const struct b43_sprom_raw *raw = of_device_get_match_data(priv->dev); + struct ssb_sprom *sprom = &priv->sprom; + + if (raw) { + u16 template_sprom[220]; + + memcpy(template_sprom, raw->map, raw->size * sizeof(u16)); + b43_sprom_fixup(priv, template_sprom); + sprom_extract(sprom, template_sprom, raw->size); + + priv->devid_override = sprom_override_devid(priv, sprom, + template_sprom); + } else { + sprom->revision = 0x02; + sprom->board_rev = 0x0017; + sprom->country_code = 0x00; + sprom->ant_available_bg = 0x03; + sprom->pa0b0 = 0x15ae; + sprom->pa0b1 = 0xfa85; + sprom->pa0b2 = 0xfe8d; + sprom->pa1b0 = 0xffff; + sprom->pa1b1 = 0xffff; + sprom->pa1b2 = 0xffff; + sprom->gpio0 = 0xff; + sprom->gpio1 = 0xff; + sprom->gpio2 = 0xff; + sprom->gpio3 = 0xff; + sprom->maxpwr_bg = 0x4c; + sprom->itssi_bg = 0x00; + sprom->boardflags_lo = 0x2848; + sprom->boardflags_hi = 0x0000; + priv->devid_override = 0; + } +} + +#if defined(CONFIG_SSB_PCIHOST) +int b43_get_fallback_ssb_sprom(struct ssb_bus *bus, struct ssb_sprom *out) +{ + struct b43_sprom *priv = &b43_sprom; + + if (bus->bustype == SSB_BUSTYPE_PCI) { + if (bus->host_pci->bus->number != priv->pci_bus || + PCI_SLOT(bus->host_pci->devfn) != priv->pci_dev) + pr_warn("ssb_fallback_sprom: pci bus/device num " + "mismatch: expected %i/%i, but got %i/%i\n", + priv->pci_bus, priv->pci_dev, + bus->host_pci->bus->number, + PCI_SLOT(bus->host_pci->devfn)); + if (priv->devid_override) + bus->host_pci->device = priv->sprom.dev_id; + memcpy(out, &priv->sprom, sizeof(struct ssb_sprom)); + return 0; + } else { + pr_err("%s: unable to fill SPROM for given bustype.\n", + __func__); + return -EINVAL; + } +} +#endif /* CONFIG_SSB_PCIHOST */ + +#if defined(CONFIG_BCMA_HOST_PCI) +int b43_get_fallback_bcma_sprom(struct bcma_bus *bus, struct ssb_sprom *out) +{ + struct b43_sprom *priv = &b43_sprom; + + if (bus->hosttype == BCMA_HOSTTYPE_PCI) { + if (bus->host_pci->bus->number != priv->pci_bus || + PCI_SLOT(bus->host_pci->devfn) != priv->pci_dev) + pr_warn("bcma_fallback_sprom: pci bus/device num " + "mismatch: expected %i/%i, but got %i/%i\n", + priv->pci_bus, priv->pci_dev, + bus->host_pci->bus->number, + PCI_SLOT(bus->host_pci->devfn)); + if (priv->devid_override) + bus->host_pci->device = priv->sprom.dev_id; + memcpy(out, &priv->sprom, sizeof(struct ssb_sprom)); + return 0; + } else { + pr_err("%s: unable to fill SPROM for given bustype.\n", + __func__); + return -EINVAL; + } +} +#endif /* CONFIG_BCMA_HOST_PCI */ + +static int b43_sprom_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *node = dev->of_node; + struct b43_sprom *priv = &b43_sprom; + const void *mac; + int ret; + + priv->dev = dev; + + b43_sprom_set(priv); + + of_property_read_u32(node, "pci-bus", &priv->pci_bus); + of_property_read_u32(node, "pci-dev", &priv->pci_dev); + + mac = of_get_mac_address(node); + if (!IS_ERR_OR_NULL(mac)) { + memcpy(priv->mac, mac, ETH_ALEN); + dev_info(dev, "mtd mac %pM\n", priv->mac); + } else { + random_ether_addr(priv->mac); + dev_info(dev, "random mac %pM\n", priv->mac); + } + + memcpy(priv->sprom.il0mac, priv->mac, ETH_ALEN); + memcpy(priv->sprom.et0mac, priv->mac, ETH_ALEN); + memcpy(priv->sprom.et1mac, priv->mac, ETH_ALEN); + +#if defined(CONFIG_SSB_PCIHOST) + ret = ssb_arch_register_fallback_sprom(&b43_get_fallback_ssb_sprom); + if (ret) + return ret; +#endif /* CONFIG_SSB_PCIHOST */ + +#if defined(CONFIG_BCMA_HOST_PCI) + ret = bcma_arch_register_fallback_sprom(b43_get_fallback_bcma_sprom); + if (ret) + return ret; +#endif /* CONFIG_BCMA_HOST_PCI */ + + return 0; +} + +static const struct of_device_id b43_sprom_of_match[] = { + { .compatible = "brcm,bcm43xx-sprom", .data = NULL }, +#if defined (CONFIG_SSB_PCIHOST) + { .compatible = "brcm,bcm4306-sprom", .data = &bcm4306_sprom, }, + { .compatible = "brcm,bcm4321-sprom", .data = &bcm4321_sprom, }, + { .compatible = "brcm,bcm4322-sprom", .data = &bcm4322_sprom, }, + { .compatible = "brcm,bcm43222-sprom", .data = &bcm43222_sprom, }, +#endif /* CONFIG_BCMA_HOST_PCI */ +#if defined(CONFIG_BCMA_HOST_PCI) + { .compatible = "brcm,bcm4313-sprom", .data = &bcm4313_sprom, }, + { .compatible = "brcm,bcm4331-sprom", .data = &bcm4331_sprom, }, + { .compatible = "brcm,bcm43131-sprom", .data = &bcm43131_sprom, }, + { .compatible = "brcm,bcm43217-sprom", .data = &bcm43217_sprom, }, + { .compatible = "brcm,bcm43225-sprom", .data = &bcm43225_sprom, }, + { .compatible = "brcm,bcm43227-sprom", .data = &bcm43227_sprom, }, + { .compatible = "brcm,bcm43228-sprom", .data = &bcm43228_sprom, }, +#endif /* CONFIG_BCMA_HOST_PCI */ + { /* sentinel */ } +}; + +static struct platform_driver b43_sprom_driver = { + .probe = b43_sprom_probe, + .driver = { + .name = "b43-sprom", + .of_match_table = b43_sprom_of_match, + }, +}; + +int __init b43_sprom_init(void) +{ + int ret = platform_driver_register(&b43_sprom_driver); + if (ret) + pr_err("b43-sprom: Error registering platform driver!\n"); + return ret; +} +late_initcall(b43_sprom_init); diff --git a/target/linux/bmips/patches-5.10/610-mips-bmips-add-pci-fixups.patch b/target/linux/bmips/patches-5.10/610-mips-bmips-add-pci-fixups.patch new file mode 100644 index 0000000000..cc393c4223 --- /dev/null +++ b/target/linux/bmips/patches-5.10/610-mips-bmips-add-pci-fixups.patch @@ -0,0 +1,6 @@ +--- a/arch/mips/bmips/Makefile ++++ b/arch/mips/bmips/Makefile +@@ -1,2 +1,3 @@ + # SPDX-License-Identifier: GPL-2.0-only + obj-y += setup.o irq.o dma.o ++obj-y += b43-sprom.o From 2024547e1f71ddbf94deecc5e2789d802f748377 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Tue, 23 Mar 2021 20:16:37 +0100 Subject: [PATCH 06/31] bmips: add ATH9K PCI fixups MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add support for registering ATH9K PCI fixups needed to bring up wifi on some devices. Signed-off-by: Álvaro Fernández Rojas --- .../bmips/dts/bcm6358-huawei-hg556a-b.dts | 15 ++ .../bmips/files/arch/mips/bmips/ath9k-fixup.c | 240 ++++++++++++++++++ .../610-mips-bmips-add-pci-fixups.patch | 2 +- 3 files changed, 256 insertions(+), 1 deletion(-) create mode 100644 target/linux/bmips/files/arch/mips/bmips/ath9k-fixup.c diff --git a/target/linux/bmips/dts/bcm6358-huawei-hg556a-b.dts b/target/linux/bmips/dts/bcm6358-huawei-hg556a-b.dts index 0f21ca4a6b..65b4480ee1 100644 --- a/target/linux/bmips/dts/bcm6358-huawei-hg556a-b.dts +++ b/target/linux/bmips/dts/bcm6358-huawei-hg556a-b.dts @@ -119,6 +119,21 @@ gpios = <&pinctrl 28 GPIO_ACTIVE_LOW>; }; }; + + ath9k-fixup { + compatible = "brcm,ath9k-fixup"; + reg = <0x30000000 0x8000000>; + + pci-dev = <1>; + + mtd-mac-address = <&cfe 0x6a0>; + mtd-mac-address-increment = <1>; + + ath,eeprom = <&cal_data 0x1e000>; + ath,endian-check; + ath,led-pin = <2>; + ath,led-active-high; + }; }; &ehci { diff --git a/target/linux/bmips/files/arch/mips/bmips/ath9k-fixup.c b/target/linux/bmips/files/arch/mips/bmips/ath9k-fixup.c new file mode 100644 index 0000000000..dd13ac6256 --- /dev/null +++ b/target/linux/bmips/files/arch/mips/bmips/ath9k-fixup.c @@ -0,0 +1,240 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * ATH9K Fixup Driver + * + * Copyright (C) 2020 Álvaro Fernández Rojas + * Copyright (C) 2014 Jonas Gorski + * Copyright (C) 2008 Maxime Bizon + * Copyright (C) 2008 Florian Fainelli + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ATH9K_MAX_FIXUPS 2 + +#define ATH9K_DEF_LED_PIN -1 +#define ATH9K_DEF_PCI_DEV 255 + +struct ath9k_fixup { + struct device *dev; + struct resource *mem_res; + u32 pci_dev; + u8 mac[ETH_ALEN]; + struct ath9k_platform_data pdata; +}; + +static int ath9k_num_fixups; +static struct ath9k_fixup *ath9k_fixups[ATH9K_MAX_FIXUPS]; + +static void ath9k_pci_fixup(struct pci_dev *dev) +{ + void __iomem *mem; + struct ath9k_fixup *priv = NULL; + struct ath9k_platform_data *pdata = NULL; + struct pci_dev *bridge = pci_upstream_bridge(dev); + u16 *cal_data = NULL; + u16 cmd; + u32 bar0; + u32 val; + unsigned i; + + for (i = 0; i < ath9k_num_fixups; i++) { + if (ath9k_fixups[i]->pci_dev != PCI_SLOT(dev->devfn)) + continue; + + priv = ath9k_fixups[i]; + cal_data = priv->pdata.eeprom_data; + pdata = &priv->pdata; + break; + } + + if (cal_data == NULL) + return; + + if (*cal_data != 0xa55a) { + pr_err("pci %s: invalid calibration data\n", pci_name(dev)); + return; + } + + pr_info("pci %s: fixup device configuration\n", pci_name(dev)); + + val = priv->mem_res->start; + mem = ioremap(priv->mem_res->start, resource_size(priv->mem_res)); + if (!mem) { + pr_err("pci %s: ioremap error\n", pci_name(dev)); + return; + } + + if (bridge) + pci_enable_device(bridge); + + pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &bar0); + pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &bar0); + pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, val); + + pci_read_config_word(dev, PCI_COMMAND, &cmd); + cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; + pci_write_config_word(dev, PCI_COMMAND, cmd); + + /* set offset to first reg address */ + cal_data += 3; + while(*cal_data != 0xffff) { + u32 reg; + + reg = *cal_data++; + val = *cal_data++; + val |= (*cal_data++) << 16; + + writel(val, mem + reg); + udelay(100); + } + + pci_read_config_dword(dev, PCI_VENDOR_ID, &val); + dev->vendor = val & 0xffff; + dev->device = (val >> 16) & 0xffff; + + pci_read_config_dword(dev, PCI_CLASS_REVISION, &val); + dev->revision = val & 0xff; + dev->class = val >> 8; /* upper 3 bytes */ + + pci_read_config_word(dev, PCI_COMMAND, &cmd); + cmd &= ~(PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY); + pci_write_config_word(dev, PCI_COMMAND, cmd); + + pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, bar0); + + if (bridge) + pci_disable_device(bridge); + + iounmap(mem); + + dev->dev.platform_data = pdata; +} +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATHEROS, PCI_ANY_ID, ath9k_pci_fixup); + +static int ath9k_mtd_eeprom(struct ath9k_fixup *priv) +{ + struct device *dev = priv->dev; + struct device_node *node = dev->of_node; + struct device_node *mtd_np = NULL; + struct mtd_info *the_mtd; + phandle phandle; + size_t eeprom_readlen; + const char *part; + const __be32 *list; + int ret, i; + + list = of_get_property(node, "ath,eeprom", &i); + if (!list || (i != (2 * sizeof(*list)))) + return -ENODEV; + + phandle = be32_to_cpup(list++); + if (phandle) + mtd_np = of_find_node_by_phandle(phandle); + if (!mtd_np) + return -ENODEV; + + part = of_get_property(mtd_np, "label", NULL); + if (!part) + part = mtd_np->name; + + the_mtd = get_mtd_device_nm(part); + if (IS_ERR(the_mtd)) + return -ENODEV; + + ret = mtd_read(the_mtd, be32_to_cpup(list), + ATH9K_PLAT_EEP_MAX_WORDS * sizeof(u16), + &eeprom_readlen, (void *) priv->pdata.eeprom_data); + put_mtd_device(the_mtd); + if (ret) + return ret; + + return 0; +} + +static int ath9k_fixup_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *node = dev->of_node; + struct ath9k_fixup *priv; + struct resource *res; + const void *mac; + int ret; + + if (ath9k_num_fixups >= ATH9K_MAX_FIXUPS) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -EINVAL; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->dev = dev; + priv->mem_res = res; + + ret = of_property_read_u32(node, "pci-dev", &priv->pci_dev); + if (ret) + priv->pci_dev = ATH9K_DEF_PCI_DEV; + + ret = ath9k_mtd_eeprom(priv); + if (ret) + return ret; + + priv->pdata.endian_check = of_property_read_bool(node, + "ath,endian-check"); + ret = of_property_read_s32(node, "ath,led-pin", &priv->pdata.led_pin); + if (ret) + priv->pdata.led_pin = ATH9K_DEF_LED_PIN; + priv->pdata.led_active_high = of_property_read_bool(node, + "ath,led-active-high"); + + mac = of_get_mac_address(node); + if (!IS_ERR_OR_NULL(mac)) { + memcpy(priv->mac, mac, ETH_ALEN); + dev_info(dev, "mtd mac %pM\n", priv->mac); + } else { + random_ether_addr(priv->mac); + dev_info(dev, "random mac %pM\n", priv->mac); + } + + priv->pdata.macaddr = priv->mac; + + ath9k_fixups[ath9k_num_fixups] = priv; + ath9k_num_fixups++; + + return 0; +} + +static const struct of_device_id ath9k_fixup_of_match[] = { + { .compatible = "brcm,ath9k-fixup" }, + { /* sentinel */ } +}; + +static struct platform_driver ath9k_fixup_driver = { + .probe = ath9k_fixup_probe, + .driver = { + .name = "ath9k-fixup", + .of_match_table = ath9k_fixup_of_match, + }, +}; + +int __init ath9k_fixup_init(void) +{ + int ret = platform_driver_register(&ath9k_fixup_driver); + if (ret) + pr_err("ath9k_fixup: Error registering platform driver!\n"); + return ret; +} +late_initcall(ath9k_fixup_init); diff --git a/target/linux/bmips/patches-5.10/610-mips-bmips-add-pci-fixups.patch b/target/linux/bmips/patches-5.10/610-mips-bmips-add-pci-fixups.patch index cc393c4223..5f68308986 100644 --- a/target/linux/bmips/patches-5.10/610-mips-bmips-add-pci-fixups.patch +++ b/target/linux/bmips/patches-5.10/610-mips-bmips-add-pci-fixups.patch @@ -3,4 +3,4 @@ @@ -1,2 +1,3 @@ # SPDX-License-Identifier: GPL-2.0-only obj-y += setup.o irq.o dma.o -+obj-y += b43-sprom.o ++obj-y += ath9k-fixup.o b43-sprom.o From 07c49462ad2ac3f6386bb4463546509f3bf35e39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Tue, 23 Mar 2021 20:23:47 +0100 Subject: [PATCH 07/31] bmips: add wifi packages for supported devices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Netgear DGND3700v2 / Comtrend VR-3032u internal wireless not supported. Signed-off-by: Álvaro Fernández Rojas --- target/linux/bmips/image/Makefile | 2 ++ target/linux/bmips/image/bcm63xx_generic.mk | 8 ++++---- target/linux/bmips/image/bcm63xx_nand.mk | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/target/linux/bmips/image/Makefile b/target/linux/bmips/image/Makefile index c1534a88db..89cd04b0ec 100644 --- a/target/linux/bmips/image/Makefile +++ b/target/linux/bmips/image/Makefile @@ -249,6 +249,8 @@ define Device/Default DEVICE_LOADADDR := endef +ATH9K_PACKAGES := kmod-ath9k wpad-basic-wolfssl +B43_PACKAGES := kmod-b43 wpad-basic-wolfssl USB1_PACKAGES := kmod-usb-ohci kmod-ledtrig-usbdev USB2_PACKAGES := $(USB1_PACKAGES) kmod-usb2 diff --git a/target/linux/bmips/image/bcm63xx_generic.mk b/target/linux/bmips/image/bcm63xx_generic.mk index 6f9a7b9a49..33282bd1a5 100644 --- a/target/linux/bmips/image/bcm63xx_generic.mk +++ b/target/linux/bmips/image/bcm63xx_generic.mk @@ -33,7 +33,7 @@ define Device/comtrend_ar-5315u CHIP_ID := 6318 CFE_BOARD_ID := 96318A-1441N1 FLASH_MB := 16 - DEVICE_PACKAGES += $(USB2_PACKAGES) + DEVICE_PACKAGES += $(USB2_PACKAGES) $(B43_PACKAGES) endef TARGET_DEVICES += comtrend_ar-5315u @@ -44,7 +44,7 @@ define Device/comtrend_ar-5387un CHIP_ID := 6328 CFE_BOARD_ID := 96328A-1441N1 FLASH_MB := 16 - DEVICE_PACKAGES += $(USB2_PACKAGES) + DEVICE_PACKAGES += $(USB2_PACKAGES) $(B43_PACKAGES) endef TARGET_DEVICES += comtrend_ar-5387un @@ -56,7 +56,7 @@ define Device/comtrend_vr-3025u CFE_BOARD_ID := 96368M-1541N BLOCKSIZE := 0x20000 FLASH_MB := 32 - DEVICE_PACKAGES += $(USB2_PACKAGES) + DEVICE_PACKAGES += $(USB2_PACKAGES) $(B43_PACKAGES) endef TARGET_DEVICES += comtrend_vr-3025u @@ -69,6 +69,6 @@ define Device/huawei_hg556a-b CFE_BOARD_ID := HW556 CFE_EXTRAS += --rsa-signature "EchoLife_HG556a" --tag-version 8 BLOCKSIZE := 0x20000 - DEVICE_PACKAGES += $(USB2_PACKAGES) + DEVICE_PACKAGES += $(USB2_PACKAGES) $(ATH9K_PACKAGES) endef TARGET_DEVICES += huawei_hg556a-b diff --git a/target/linux/bmips/image/bcm63xx_nand.mk b/target/linux/bmips/image/bcm63xx_nand.mk index a712cd0699..82b04891d5 100644 --- a/target/linux/bmips/image/bcm63xx_nand.mk +++ b/target/linux/bmips/image/bcm63xx_nand.mk @@ -74,7 +74,7 @@ define Device/netgear_dgnd3700-v2 CFE_RAM_JFFS2_PAD := 496k BLOCKSIZE := 16k PAGESIZE := 512 - DEVICE_PACKAGES += $(USB2_PACKAGES) + DEVICE_PACKAGES += $(USB2_PACKAGES) $(B43_PACKAGES) CFE_WFI_FLASH_TYPE := 2 CFE_WFI_VERSION := 0x5731 endef From eb964298b38784aa39de1c718d200cffbf96e066 Mon Sep 17 00:00:00 2001 From: Kevin Darbyshire-Bryant Date: Fri, 19 Mar 2021 15:21:25 +0000 Subject: [PATCH 08/31] kernel: bump 5.10 to 5.10.24 Straightforward refresh of patches using update_kernel. Run tested: x86_64 (apu2) Signed-off-by: Kevin Darbyshire-Bryant --- include/kernel-version.mk | 4 +- .../802-usb-xhci-force-msi-renesas-xhci.patch | 4 +- .../0036-GPIO-add-named-gpio-exports.patch | 4 +- ...tree-gpio-hogs-on-dual-role-gpio-pin.patch | 4 +- ...t-a-central-TX-reallocation-procedur.patch | 104 ------------------ ...tag_brcm-add-support-for-legacy-tags.patch | 4 +- ...r-when-a-non-legacy-FDB-operation-fa.patch | 4 +- ...e-switchdev_notifier_fdb_info-in-dsa.patch | 8 +- ...tchdev-event-implementation-under-th.patch | 4 +- ...ly-in-dsa_slave_switchdev_event-if-w.patch | 2 +- ...or-SWITCHDEV_-FDB-DEL-_ADD_TO_DEVICE.patch | 6 +- ...e_mem_map-with-ARCH_PFN_OFFSET-calcu.patch | 2 +- ...-forwarding-path-for-dsa-slave-ports.patch | 4 +- ...sa-slave-add-support-for-TC_SETUP_FT.patch | 2 +- ...detach-callback-to-struct-phy_driver.patch | 2 +- ...local-addresses-in-assisted-CPU-port.patch | 2 +- ...bridge-addresses-in-assisted-CPU-por.patch | 2 +- ...tic-FDB-entries-on-foreign-interface.patch | 4 +- ...y-simplify-phy_link_change-arguments.patch | 10 +- .../721-NET-no-auto-carrier-off-support.patch | 4 +- .../800-GPIO-add-named-gpio-exports.patch | 4 +- .../200-pcengines-apu2-reboot.patch | 2 +- 22 files changed, 41 insertions(+), 145 deletions(-) delete mode 100644 target/linux/bmips/patches-5.10/010-v5.11-net-dsa-implement-a-central-TX-reallocation-procedur.patch diff --git a/include/kernel-version.mk b/include/kernel-version.mk index b5762dd831..1b91ef82fa 100644 --- a/include/kernel-version.mk +++ b/include/kernel-version.mk @@ -7,10 +7,10 @@ ifdef CONFIG_TESTING_KERNEL endif LINUX_VERSION-5.4 = .106 -LINUX_VERSION-5.10 = .23 +LINUX_VERSION-5.10 = .24 LINUX_KERNEL_HASH-5.4.106 = cc873b2c39c1823d4bc4f6cde527943c8cfd28ae94cb517804b0f9679359c8db -LINUX_KERNEL_HASH-5.10.23 = f6e21c03ec6ff85b26d77c59fdab81e64707792a57593643307df192749edb6a +LINUX_KERNEL_HASH-5.10.24 = c6dcd04e5893c5d68b637188f904528e91f28d790cd49cf8a7fb817423bd763f remove_uri_prefix=$(subst git://,,$(subst http://,,$(subst https://,,$(1)))) sanitize_uri=$(call qstrip,$(subst @,_,$(subst :,_,$(subst .,_,$(subst -,_,$(subst /,_,$(1))))))) diff --git a/target/linux/apm821xx/patches-5.10/802-usb-xhci-force-msi-renesas-xhci.patch b/target/linux/apm821xx/patches-5.10/802-usb-xhci-force-msi-renesas-xhci.patch index 5de02ae679..ed557fd0dc 100644 --- a/target/linux/apm821xx/patches-5.10/802-usb-xhci-force-msi-renesas-xhci.patch +++ b/target/linux/apm821xx/patches-5.10/802-usb-xhci-force-msi-renesas-xhci.patch @@ -13,7 +13,7 @@ produce a noisy warning. --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c -@@ -260,6 +260,7 @@ static void xhci_pci_quirks(struct devic +@@ -261,6 +261,7 @@ static void xhci_pci_quirks(struct devic pdev->device == 0x0015) { xhci->quirks |= XHCI_RESET_ON_RESUME; xhci->quirks |= XHCI_ZERO_64B_REGS; @@ -43,7 +43,7 @@ produce a noisy warning. hcd->msi_enabled = 1; --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h -@@ -1886,6 +1886,7 @@ struct xhci_hcd { +@@ -1887,6 +1887,7 @@ struct xhci_hcd { struct xhci_hub usb2_rhub; struct xhci_hub usb3_rhub; /* support xHCI 1.0 spec USB2 hardware LPM */ diff --git a/target/linux/ath79/patches-5.10/0036-GPIO-add-named-gpio-exports.patch b/target/linux/ath79/patches-5.10/0036-GPIO-add-named-gpio-exports.patch index fe34f0b21b..09bad30109 100644 --- a/target/linux/ath79/patches-5.10/0036-GPIO-add-named-gpio-exports.patch +++ b/target/linux/ath79/patches-5.10/0036-GPIO-add-named-gpio-exports.patch @@ -141,7 +141,7 @@ Signed-off-by: John Crispin { --- a/include/linux/gpio/consumer.h +++ b/include/linux/gpio/consumer.h -@@ -713,6 +713,7 @@ static inline void devm_acpi_dev_remove_ +@@ -715,6 +715,7 @@ static inline void devm_acpi_dev_remove_ #if IS_ENABLED(CONFIG_GPIOLIB) && IS_ENABLED(CONFIG_GPIO_SYSFS) @@ -149,7 +149,7 @@ Signed-off-by: John Crispin int gpiod_export(struct gpio_desc *desc, bool direction_may_change); int gpiod_export_link(struct device *dev, const char *name, struct gpio_desc *desc); -@@ -720,6 +721,13 @@ void gpiod_unexport(struct gpio_desc *de +@@ -722,6 +723,13 @@ void gpiod_unexport(struct gpio_desc *de #else /* CONFIG_GPIOLIB && CONFIG_GPIO_SYSFS */ diff --git a/target/linux/bcm63xx/patches-5.10/143-gpio-fix-device-tree-gpio-hogs-on-dual-role-gpio-pin.patch b/target/linux/bcm63xx/patches-5.10/143-gpio-fix-device-tree-gpio-hogs-on-dual-role-gpio-pin.patch index 0011c7a0e6..2b58b4841a 100644 --- a/target/linux/bcm63xx/patches-5.10/143-gpio-fix-device-tree-gpio-hogs-on-dual-role-gpio-pin.patch +++ b/target/linux/bcm63xx/patches-5.10/143-gpio-fix-device-tree-gpio-hogs-on-dual-role-gpio-pin.patch @@ -116,7 +116,7 @@ Signed-off-by: Jonas Gorski } --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c -@@ -1886,7 +1886,8 @@ int gpiochip_add_pingroup_range(struct g +@@ -1890,7 +1890,8 @@ int gpiochip_add_pingroup_range(struct g list_add_tail(&pin_range->node, &gdev->pin_ranges); @@ -126,7 +126,7 @@ Signed-off-by: Jonas Gorski } EXPORT_SYMBOL_GPL(gpiochip_add_pingroup_range); -@@ -1943,7 +1944,7 @@ int gpiochip_add_pin_range(struct gpio_c +@@ -1947,7 +1948,7 @@ int gpiochip_add_pin_range(struct gpio_c list_add_tail(&pin_range->node, &gdev->pin_ranges); diff --git a/target/linux/bmips/patches-5.10/010-v5.11-net-dsa-implement-a-central-TX-reallocation-procedur.patch b/target/linux/bmips/patches-5.10/010-v5.11-net-dsa-implement-a-central-TX-reallocation-procedur.patch deleted file mode 100644 index 4171a69d1d..0000000000 --- a/target/linux/bmips/patches-5.10/010-v5.11-net-dsa-implement-a-central-TX-reallocation-procedur.patch +++ /dev/null @@ -1,104 +0,0 @@ -From a3b0b6479700a5b0af2c631cb2ec0fb7a0d978f2 Mon Sep 17 00:00:00 2001 -From: Vladimir Oltean -Date: Sun, 1 Nov 2020 21:16:09 +0200 -Subject: [PATCH] net: dsa: implement a central TX reallocation procedure - -At the moment, taggers are left with the task of ensuring that the skb -headers are writable (which they aren't, if the frames were cloned for -TX timestamping, for flooding by the bridge, etc), and that there is -enough space in the skb data area for the DSA tag to be pushed. - -Moreover, the life of tail taggers is even harder, because they need to -ensure that short frames have enough padding, a problem that normal -taggers don't have. - -The principle of the DSA framework is that everything except for the -most intimate hardware specifics (like in this case, the actual packing -of the DSA tag bits) should be done inside the core, to avoid having -code paths that are very rarely tested. - -So provide a TX reallocation procedure that should cover the known needs -of DSA today. - -Note that this patch also gives the network stack a good hint about the -headroom/tailroom it's going to need. Up till now it wasn't doing that. -So the reallocation procedure should really be there only for the -exceptional cases, and for cloned packets which need to be unshared. - -Signed-off-by: Vladimir Oltean -Tested-by: Christian Eggers # For tail taggers only -Tested-by: Kurt Kanzenbach -Reviewed-by: Florian Fainelli -Signed-off-by: Jakub Kicinski ---- - net/dsa/slave.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 45 insertions(+) - ---- a/net/dsa/slave.c -+++ b/net/dsa/slave.c -@@ -548,6 +548,30 @@ netdev_tx_t dsa_enqueue_skb(struct sk_bu - } - EXPORT_SYMBOL_GPL(dsa_enqueue_skb); - -+static int dsa_realloc_skb(struct sk_buff *skb, struct net_device *dev) -+{ -+ int needed_headroom = dev->needed_headroom; -+ int needed_tailroom = dev->needed_tailroom; -+ -+ /* For tail taggers, we need to pad short frames ourselves, to ensure -+ * that the tail tag does not fail at its role of being at the end of -+ * the packet, once the master interface pads the frame. Account for -+ * that pad length here, and pad later. -+ */ -+ if (unlikely(needed_tailroom && skb->len < ETH_ZLEN)) -+ needed_tailroom += ETH_ZLEN - skb->len; -+ /* skb_headroom() returns unsigned int... */ -+ needed_headroom = max_t(int, needed_headroom - skb_headroom(skb), 0); -+ needed_tailroom = max_t(int, needed_tailroom - skb_tailroom(skb), 0); -+ -+ if (likely(!needed_headroom && !needed_tailroom && !skb_cloned(skb))) -+ /* No reallocation needed, yay! */ -+ return 0; -+ -+ return pskb_expand_head(skb, needed_headroom, needed_tailroom, -+ GFP_ATOMIC); -+} -+ - static netdev_tx_t dsa_slave_xmit(struct sk_buff *skb, struct net_device *dev) - { - struct dsa_slave_priv *p = netdev_priv(dev); -@@ -567,6 +591,17 @@ static netdev_tx_t dsa_slave_xmit(struct - */ - dsa_skb_tx_timestamp(p, skb); - -+ if (dsa_realloc_skb(skb, dev)) { -+ dev_kfree_skb_any(skb); -+ return NETDEV_TX_OK; -+ } -+ -+ /* needed_tailroom should still be 'warm' in the cache line from -+ * dsa_realloc_skb(), which has also ensured that padding is safe. -+ */ -+ if (dev->needed_tailroom) -+ eth_skb_pad(skb); -+ - /* Transmit function may have to reallocate the original SKB, - * in which case it must have freed it. Only free it here on error. - */ -@@ -1825,6 +1860,16 @@ int dsa_slave_create(struct dsa_port *po - slave_dev->netdev_ops = &dsa_slave_netdev_ops; - if (ds->ops->port_max_mtu) - slave_dev->max_mtu = ds->ops->port_max_mtu(ds, port->index); -+ if (cpu_dp->tag_ops->tail_tag) -+ slave_dev->needed_tailroom = cpu_dp->tag_ops->overhead; -+ else -+ slave_dev->needed_headroom = cpu_dp->tag_ops->overhead; -+ /* Try to save one extra realloc later in the TX path (in the master) -+ * by also inheriting the master's needed headroom and tailroom. -+ * The 8021q driver also does this. -+ */ -+ slave_dev->needed_headroom += master->needed_headroom; -+ slave_dev->needed_tailroom += master->needed_tailroom; - SET_NETDEV_DEVTYPE(slave_dev, &dsa_type); - - netdev_for_each_tx_queue(slave_dev, dsa_slave_set_lockdep_class_one, diff --git a/target/linux/bmips/patches-5.10/049-v5.13-net-dsa-tag_brcm-add-support-for-legacy-tags.patch b/target/linux/bmips/patches-5.10/049-v5.13-net-dsa-tag_brcm-add-support-for-legacy-tags.patch index a9b689ca9c..c689bc84d1 100644 --- a/target/linux/bmips/patches-5.10/049-v5.13-net-dsa-tag_brcm-add-support-for-legacy-tags.patch +++ b/target/linux/bmips/patches-5.10/049-v5.13-net-dsa-tag_brcm-add-support-for-legacy-tags.patch @@ -80,7 +80,7 @@ Signed-off-by: David S. Miller #define BRCM_TAG_LEN 4 /* Tag is constructed and desconstructed using byte by byte access -@@ -197,6 +214,87 @@ DSA_TAG_DRIVER(brcm_netdev_ops); +@@ -194,6 +211,87 @@ DSA_TAG_DRIVER(brcm_netdev_ops); MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_BRCM); #endif @@ -168,7 +168,7 @@ Signed-off-by: David S. Miller #if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM_PREPEND) static struct sk_buff *brcm_tag_xmit_prepend(struct sk_buff *skb, struct net_device *dev) -@@ -229,6 +327,9 @@ static struct dsa_tag_driver *dsa_tag_dr +@@ -226,6 +324,9 @@ static struct dsa_tag_driver *dsa_tag_dr #if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM) &DSA_TAG_DRIVER_NAME(brcm_netdev_ops), #endif diff --git a/target/linux/generic/backport-5.10/771-v5.12-net-dsa-be-louder-when-a-non-legacy-FDB-operation-fa.patch b/target/linux/generic/backport-5.10/771-v5.12-net-dsa-be-louder-when-a-non-legacy-FDB-operation-fa.patch index e4fd9eb2e4..ecb81004cb 100644 --- a/target/linux/generic/backport-5.10/771-v5.12-net-dsa-be-louder-when-a-non-legacy-FDB-operation-fa.patch +++ b/target/linux/generic/backport-5.10/771-v5.12-net-dsa-be-louder-when-a-non-legacy-FDB-operation-fa.patch @@ -25,7 +25,7 @@ Signed-off-by: Jakub Kicinski --- a/net/dsa/slave.c +++ b/net/dsa/slave.c -@@ -2030,7 +2030,9 @@ static void dsa_slave_switchdev_event_wo +@@ -2075,7 +2075,9 @@ static void dsa_slave_switchdev_event_wo err = dsa_port_fdb_add(dp, fdb_info->addr, fdb_info->vid); if (err) { @@ -36,7 +36,7 @@ Signed-off-by: Jakub Kicinski break; } fdb_info->offloaded = true; -@@ -2045,9 +2047,11 @@ static void dsa_slave_switchdev_event_wo +@@ -2090,9 +2092,11 @@ static void dsa_slave_switchdev_event_wo err = dsa_port_fdb_del(dp, fdb_info->addr, fdb_info->vid); if (err) { diff --git a/target/linux/generic/backport-5.10/772-v5.12-net-dsa-don-t-use-switchdev_notifier_fdb_info-in-dsa.patch b/target/linux/generic/backport-5.10/772-v5.12-net-dsa-don-t-use-switchdev_notifier_fdb_info-in-dsa.patch index 31502f5b23..bb943f1312 100644 --- a/target/linux/generic/backport-5.10/772-v5.12-net-dsa-don-t-use-switchdev_notifier_fdb_info-in-dsa.patch +++ b/target/linux/generic/backport-5.10/772-v5.12-net-dsa-don-t-use-switchdev_notifier_fdb_info-in-dsa.patch @@ -54,7 +54,7 @@ Signed-off-by: Jakub Kicinski struct sk_buff * (*xmit)(struct sk_buff *skb, --- a/net/dsa/slave.c +++ b/net/dsa/slave.c -@@ -2005,76 +2005,66 @@ static int dsa_slave_netdevice_event(str +@@ -2050,76 +2050,66 @@ static int dsa_slave_netdevice_event(str return NOTIFY_DONE; } @@ -167,7 +167,7 @@ Signed-off-by: Jakub Kicinski } /* Called under rcu_read_lock() */ -@@ -2082,7 +2072,9 @@ static int dsa_slave_switchdev_event(str +@@ -2127,7 +2117,9 @@ static int dsa_slave_switchdev_event(str unsigned long event, void *ptr) { struct net_device *dev = switchdev_notifier_info_to_dev(ptr); @@ -177,7 +177,7 @@ Signed-off-by: Jakub Kicinski int err; if (event == SWITCHDEV_PORT_ATTR_SET) { -@@ -2095,20 +2087,32 @@ static int dsa_slave_switchdev_event(str +@@ -2140,20 +2132,32 @@ static int dsa_slave_switchdev_event(str if (!dsa_slave_dev_check(dev)) return NOTIFY_DONE; @@ -213,7 +213,7 @@ Signed-off-by: Jakub Kicinski dev_hold(dev); break; default: -@@ -2118,10 +2122,6 @@ static int dsa_slave_switchdev_event(str +@@ -2163,10 +2167,6 @@ static int dsa_slave_switchdev_event(str dsa_schedule_work(&switchdev_work->work); return NOTIFY_OK; diff --git a/target/linux/generic/backport-5.10/773-v5.12-net-dsa-move-switchdev-event-implementation-under-th.patch b/target/linux/generic/backport-5.10/773-v5.12-net-dsa-move-switchdev-event-implementation-under-th.patch index 49e095a587..48c2af770b 100644 --- a/target/linux/generic/backport-5.10/773-v5.12-net-dsa-move-switchdev-event-implementation-under-th.patch +++ b/target/linux/generic/backport-5.10/773-v5.12-net-dsa-move-switchdev-event-implementation-under-th.patch @@ -20,7 +20,7 @@ Signed-off-by: Jakub Kicinski --- a/net/dsa/slave.c +++ b/net/dsa/slave.c -@@ -2077,31 +2077,29 @@ static int dsa_slave_switchdev_event(str +@@ -2122,31 +2122,29 @@ static int dsa_slave_switchdev_event(str struct dsa_port *dp; int err; @@ -68,7 +68,7 @@ Signed-off-by: Jakub Kicinski fdb_info = ptr; if (!fdb_info->added_by_user) { -@@ -2114,13 +2112,12 @@ static int dsa_slave_switchdev_event(str +@@ -2159,13 +2157,12 @@ static int dsa_slave_switchdev_event(str switchdev_work->vid = fdb_info->vid; dev_hold(dev); diff --git a/target/linux/generic/backport-5.10/774-v5.12-net-dsa-exit-early-in-dsa_slave_switchdev_event-if-w.patch b/target/linux/generic/backport-5.10/774-v5.12-net-dsa-exit-early-in-dsa_slave_switchdev_event-if-w.patch index cbf2739469..a1f56353ea 100644 --- a/target/linux/generic/backport-5.10/774-v5.12-net-dsa-exit-early-in-dsa_slave_switchdev_event-if-w.patch +++ b/target/linux/generic/backport-5.10/774-v5.12-net-dsa-exit-early-in-dsa_slave_switchdev_event-if-w.patch @@ -30,7 +30,7 @@ Signed-off-by: Jakub Kicinski --- a/net/dsa/slave.c +++ b/net/dsa/slave.c -@@ -2090,6 +2090,9 @@ static int dsa_slave_switchdev_event(str +@@ -2135,6 +2135,9 @@ static int dsa_slave_switchdev_event(str dp = dsa_slave_to_port(dev); diff --git a/target/linux/generic/backport-5.10/775-v5.12-net-dsa-listen-for-SWITCHDEV_-FDB-DEL-_ADD_TO_DEVICE.patch b/target/linux/generic/backport-5.10/775-v5.12-net-dsa-listen-for-SWITCHDEV_-FDB-DEL-_ADD_TO_DEVICE.patch index 978ece93b3..e576ff8ce2 100644 --- a/target/linux/generic/backport-5.10/775-v5.12-net-dsa-listen-for-SWITCHDEV_-FDB-DEL-_ADD_TO_DEVICE.patch +++ b/target/linux/generic/backport-5.10/775-v5.12-net-dsa-listen-for-SWITCHDEV_-FDB-DEL-_ADD_TO_DEVICE.patch @@ -170,7 +170,7 @@ Signed-off-by: Jakub Kicinski */ --- a/net/dsa/slave.c +++ b/net/dsa/slave.c -@@ -2067,6 +2067,28 @@ static void dsa_slave_switchdev_event_wo +@@ -2112,6 +2112,28 @@ static void dsa_slave_switchdev_event_wo dev_put(dp->slave); } @@ -199,7 +199,7 @@ Signed-off-by: Jakub Kicinski /* Called under rcu_read_lock() */ static int dsa_slave_switchdev_event(struct notifier_block *unused, unsigned long event, void *ptr) -@@ -2085,10 +2107,37 @@ static int dsa_slave_switchdev_event(str +@@ -2130,10 +2152,37 @@ static int dsa_slave_switchdev_event(str return notifier_from_errno(err); case SWITCHDEV_FDB_ADD_TO_DEVICE: case SWITCHDEV_FDB_DEL_TO_DEVICE: @@ -240,7 +240,7 @@ Signed-off-by: Jakub Kicinski if (!dp->ds->ops->port_fdb_add || !dp->ds->ops->port_fdb_del) return NOTIFY_DONE; -@@ -2103,18 +2152,13 @@ static int dsa_slave_switchdev_event(str +@@ -2148,18 +2197,13 @@ static int dsa_slave_switchdev_event(str switchdev_work->port = dp->index; switchdev_work->event = event; diff --git a/target/linux/generic/pending-5.10/120-Fix-alloc_node_mem_map-with-ARCH_PFN_OFFSET-calcu.patch b/target/linux/generic/pending-5.10/120-Fix-alloc_node_mem_map-with-ARCH_PFN_OFFSET-calcu.patch index 4e83b98724..c0482dfee5 100644 --- a/target/linux/generic/pending-5.10/120-Fix-alloc_node_mem_map-with-ARCH_PFN_OFFSET-calcu.patch +++ b/target/linux/generic/pending-5.10/120-Fix-alloc_node_mem_map-with-ARCH_PFN_OFFSET-calcu.patch @@ -71,7 +71,7 @@ Signed-off-by: Tobias Wolf --- a/mm/page_alloc.c +++ b/mm/page_alloc.c -@@ -6951,7 +6951,7 @@ static void __ref alloc_node_mem_map(str +@@ -7026,7 +7026,7 @@ static void __ref alloc_node_mem_map(str if (pgdat == NODE_DATA(0)) { mem_map = NODE_DATA(0)->node_mem_map; if (page_to_pfn(mem_map) != pgdat->node_start_pfn) diff --git a/target/linux/generic/pending-5.10/640-12-net-dsa-resolve-forwarding-path-for-dsa-slave-ports.patch b/target/linux/generic/pending-5.10/640-12-net-dsa-resolve-forwarding-path-for-dsa-slave-ports.patch index c8f0a32dd9..0b85742290 100644 --- a/target/linux/generic/pending-5.10/640-12-net-dsa-resolve-forwarding-path-for-dsa-slave-ports.patch +++ b/target/linux/generic/pending-5.10/640-12-net-dsa-resolve-forwarding-path-for-dsa-slave-ports.patch @@ -28,7 +28,7 @@ Add .ndo_fill_forward_path for dsa slave port devices --- a/net/dsa/slave.c +++ b/net/dsa/slave.c -@@ -1582,6 +1582,21 @@ static struct devlink_port *dsa_slave_ge +@@ -1617,6 +1617,21 @@ static struct devlink_port *dsa_slave_ge return dp->ds->devlink ? &dp->devlink_port : NULL; } @@ -50,7 +50,7 @@ Add .ndo_fill_forward_path for dsa slave port devices static const struct net_device_ops dsa_slave_netdev_ops = { .ndo_open = dsa_slave_open, .ndo_stop = dsa_slave_close, -@@ -1607,6 +1622,7 @@ static const struct net_device_ops dsa_s +@@ -1642,6 +1657,7 @@ static const struct net_device_ops dsa_s .ndo_vlan_rx_kill_vid = dsa_slave_vlan_rx_kill_vid, .ndo_get_devlink_port = dsa_slave_get_devlink_port, .ndo_change_mtu = dsa_slave_change_mtu, diff --git a/target/linux/generic/pending-5.10/640-16-dsa-slave-add-support-for-TC_SETUP_FT.patch b/target/linux/generic/pending-5.10/640-16-dsa-slave-add-support-for-TC_SETUP_FT.patch index 58a2064c03..4dade26f60 100644 --- a/target/linux/generic/pending-5.10/640-16-dsa-slave-add-support-for-TC_SETUP_FT.patch +++ b/target/linux/generic/pending-5.10/640-16-dsa-slave-add-support-for-TC_SETUP_FT.patch @@ -17,7 +17,7 @@ Signed-off-by: Pablo Neira Ayuso --- a/net/dsa/slave.c +++ b/net/dsa/slave.c -@@ -1202,14 +1202,32 @@ static int dsa_slave_setup_tc_block(stru +@@ -1237,14 +1237,32 @@ static int dsa_slave_setup_tc_block(stru } } diff --git a/target/linux/generic/pending-5.10/703-phy-add-detach-callback-to-struct-phy_driver.patch b/target/linux/generic/pending-5.10/703-phy-add-detach-callback-to-struct-phy_driver.patch index ec77d59cf0..69b82c2635 100644 --- a/target/linux/generic/pending-5.10/703-phy-add-detach-callback-to-struct-phy_driver.patch +++ b/target/linux/generic/pending-5.10/703-phy-add-detach-callback-to-struct-phy_driver.patch @@ -11,7 +11,7 @@ Signed-off-by: Gabor Juhos --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c -@@ -1644,6 +1644,9 @@ void phy_detach(struct phy_device *phyde +@@ -1642,6 +1642,9 @@ void phy_detach(struct phy_device *phyde struct module *ndev_owner = NULL; struct mii_bus *bus; diff --git a/target/linux/generic/pending-5.10/765-net-dsa-Include-local-addresses-in-assisted-CPU-port.patch b/target/linux/generic/pending-5.10/765-net-dsa-Include-local-addresses-in-assisted-CPU-port.patch index 9246d1fa40..c86a854212 100644 --- a/target/linux/generic/pending-5.10/765-net-dsa-Include-local-addresses-in-assisted-CPU-port.patch +++ b/target/linux/generic/pending-5.10/765-net-dsa-Include-local-addresses-in-assisted-CPU-port.patch @@ -18,7 +18,7 @@ Signed-off-by: Tobias Waldekranz --- a/net/dsa/slave.c +++ b/net/dsa/slave.c -@@ -2144,10 +2144,12 @@ static int dsa_slave_switchdev_event(str +@@ -2189,10 +2189,12 @@ static int dsa_slave_switchdev_event(str fdb_info = ptr; if (dsa_slave_dev_check(dev)) { diff --git a/target/linux/generic/pending-5.10/766-net-dsa-Include-bridge-addresses-in-assisted-CPU-por.patch b/target/linux/generic/pending-5.10/766-net-dsa-Include-bridge-addresses-in-assisted-CPU-por.patch index 77f0dca252..bf356422de 100644 --- a/target/linux/generic/pending-5.10/766-net-dsa-Include-bridge-addresses-in-assisted-CPU-por.patch +++ b/target/linux/generic/pending-5.10/766-net-dsa-Include-bridge-addresses-in-assisted-CPU-por.patch @@ -15,7 +15,7 @@ Signed-off-by: Tobias Waldekranz --- a/net/dsa/slave.c +++ b/net/dsa/slave.c -@@ -2158,7 +2158,11 @@ static int dsa_slave_switchdev_event(str +@@ -2203,7 +2203,11 @@ static int dsa_slave_switchdev_event(str struct net_device *br_dev; struct dsa_slave_priv *p; diff --git a/target/linux/generic/pending-5.10/767-net-dsa-Sync-static-FDB-entries-on-foreign-interface.patch b/target/linux/generic/pending-5.10/767-net-dsa-Sync-static-FDB-entries-on-foreign-interface.patch index 39271108ec..84ad38f6eb 100644 --- a/target/linux/generic/pending-5.10/767-net-dsa-Sync-static-FDB-entries-on-foreign-interface.patch +++ b/target/linux/generic/pending-5.10/767-net-dsa-Sync-static-FDB-entries-on-foreign-interface.patch @@ -28,7 +28,7 @@ Signed-off-by: Tobias Waldekranz --- a/net/dsa/slave.c +++ b/net/dsa/slave.c -@@ -2151,9 +2151,12 @@ static int dsa_slave_switchdev_event(str +@@ -2196,9 +2196,12 @@ static int dsa_slave_switchdev_event(str else if (!fdb_info->added_by_user) return NOTIFY_OK; } else { @@ -44,7 +44,7 @@ Signed-off-by: Tobias Waldekranz */ struct net_device *br_dev; struct dsa_slave_priv *p; -@@ -2175,7 +2178,8 @@ static int dsa_slave_switchdev_event(str +@@ -2220,7 +2223,8 @@ static int dsa_slave_switchdev_event(str dp = p->dp->cpu_dp; diff --git a/target/linux/ramips/patches-5.10/720-Revert-net-phy-simplify-phy_link_change-arguments.patch b/target/linux/ramips/patches-5.10/720-Revert-net-phy-simplify-phy_link_change-arguments.patch index c53b11ea31..b0bdf374d9 100644 --- a/target/linux/ramips/patches-5.10/720-Revert-net-phy-simplify-phy_link_change-arguments.patch +++ b/target/linux/ramips/patches-5.10/720-Revert-net-phy-simplify-phy_link_change-arguments.patch @@ -33,7 +33,7 @@ still required by target/linux/ramips/files/drivers/net/ethernet/ralink/mdio.c phy_led_trigger_change_speed(phydev); } -@@ -616,7 +616,7 @@ int phy_start_cable_test(struct phy_devi +@@ -618,7 +618,7 @@ int phy_start_cable_test(struct phy_devi goto out; /* Mark the carrier down until the test is complete */ @@ -42,7 +42,7 @@ still required by target/linux/ramips/files/drivers/net/ethernet/ralink/mdio.c netif_testing_on(dev); err = phydev->drv->cable_test_start(phydev); -@@ -687,7 +687,7 @@ int phy_start_cable_test_tdr(struct phy_ +@@ -689,7 +689,7 @@ int phy_start_cable_test_tdr(struct phy_ goto out; /* Mark the carrier down until the test is complete */ @@ -51,7 +51,7 @@ still required by target/linux/ramips/files/drivers/net/ethernet/ralink/mdio.c netif_testing_on(dev); err = phydev->drv->cable_test_tdr_start(phydev, config); -@@ -758,7 +758,7 @@ static int phy_check_link_status(struct +@@ -760,7 +760,7 @@ static int phy_check_link_status(struct phy_link_up(phydev); } else if (!phydev->link && phydev->state != PHY_NOLINK) { phydev->state = PHY_NOLINK; @@ -60,7 +60,7 @@ still required by target/linux/ramips/files/drivers/net/ethernet/ralink/mdio.c } return 0; -@@ -1162,7 +1162,7 @@ void phy_state_machine(struct work_struc +@@ -1164,7 +1164,7 @@ void phy_state_machine(struct work_struc case PHY_HALTED: if (phydev->link) { phydev->link = 0; @@ -71,7 +71,7 @@ still required by target/linux/ramips/files/drivers/net/ethernet/ralink/mdio.c break; --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c -@@ -937,14 +937,16 @@ struct phy_device *phy_find_first(struct +@@ -935,14 +935,16 @@ struct phy_device *phy_find_first(struct } EXPORT_SYMBOL(phy_find_first); diff --git a/target/linux/ramips/patches-5.10/721-NET-no-auto-carrier-off-support.patch b/target/linux/ramips/patches-5.10/721-NET-no-auto-carrier-off-support.patch index 09170ab632..59041f0420 100644 --- a/target/linux/ramips/patches-5.10/721-NET-no-auto-carrier-off-support.patch +++ b/target/linux/ramips/patches-5.10/721-NET-no-auto-carrier-off-support.patch @@ -11,7 +11,7 @@ Signed-off-by: John Crispin --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c -@@ -758,7 +758,10 @@ static int phy_check_link_status(struct +@@ -760,7 +760,10 @@ static int phy_check_link_status(struct phy_link_up(phydev); } else if (!phydev->link && phydev->state != PHY_NOLINK) { phydev->state = PHY_NOLINK; @@ -23,7 +23,7 @@ Signed-off-by: John Crispin } return 0; -@@ -1162,7 +1165,10 @@ void phy_state_machine(struct work_struc +@@ -1164,7 +1167,10 @@ void phy_state_machine(struct work_struc case PHY_HALTED: if (phydev->link) { phydev->link = 0; diff --git a/target/linux/ramips/patches-5.10/800-GPIO-add-named-gpio-exports.patch b/target/linux/ramips/patches-5.10/800-GPIO-add-named-gpio-exports.patch index fe34f0b21b..09bad30109 100644 --- a/target/linux/ramips/patches-5.10/800-GPIO-add-named-gpio-exports.patch +++ b/target/linux/ramips/patches-5.10/800-GPIO-add-named-gpio-exports.patch @@ -141,7 +141,7 @@ Signed-off-by: John Crispin { --- a/include/linux/gpio/consumer.h +++ b/include/linux/gpio/consumer.h -@@ -713,6 +713,7 @@ static inline void devm_acpi_dev_remove_ +@@ -715,6 +715,7 @@ static inline void devm_acpi_dev_remove_ #if IS_ENABLED(CONFIG_GPIOLIB) && IS_ENABLED(CONFIG_GPIO_SYSFS) @@ -149,7 +149,7 @@ Signed-off-by: John Crispin int gpiod_export(struct gpio_desc *desc, bool direction_may_change); int gpiod_export_link(struct device *dev, const char *name, struct gpio_desc *desc); -@@ -720,6 +721,13 @@ void gpiod_unexport(struct gpio_desc *de +@@ -722,6 +723,13 @@ void gpiod_unexport(struct gpio_desc *de #else /* CONFIG_GPIOLIB && CONFIG_GPIO_SYSFS */ diff --git a/target/linux/x86/patches-5.10/200-pcengines-apu2-reboot.patch b/target/linux/x86/patches-5.10/200-pcengines-apu2-reboot.patch index bc57806c74..742b6d6ad5 100644 --- a/target/linux/x86/patches-5.10/200-pcengines-apu2-reboot.patch +++ b/target/linux/x86/patches-5.10/200-pcengines-apu2-reboot.patch @@ -1,6 +1,6 @@ --- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c -@@ -477,6 +477,16 @@ static const struct dmi_system_id reboot +@@ -486,6 +486,16 @@ static const struct dmi_system_id reboot }, }, From d07ac3e37603bac438b21286b14867e7489ed7dd Mon Sep 17 00:00:00 2001 From: Kevin Darbyshire-Bryant Date: Sat, 20 Mar 2021 11:44:57 +0000 Subject: [PATCH 09/31] kernel: bump 5.10 to 5.10.25 Straightforward refresh of patches using update_kernel. Removed (reverse-applicable): bmips/patches-5.10/010-v5.11-net-dsa-implement-a-central-TX-reallocation-procedur.patch Run tested: x86_64 (apu2) Signed-off-by: Kevin Darbyshire-Bryant --- include/kernel-version.mk | 4 ++-- .../050-v5.13-net-dsa-b53-support-legacy-tags.patch | 2 +- .../505-net-dsa-b53-add-support-for-BCM63xx-RGMIIs.patch | 6 +++--- target/linux/generic/hack-5.10/902-debloat_proc.patch | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/include/kernel-version.mk b/include/kernel-version.mk index 1b91ef82fa..2dd18d7c0b 100644 --- a/include/kernel-version.mk +++ b/include/kernel-version.mk @@ -7,10 +7,10 @@ ifdef CONFIG_TESTING_KERNEL endif LINUX_VERSION-5.4 = .106 -LINUX_VERSION-5.10 = .24 +LINUX_VERSION-5.10 = .25 LINUX_KERNEL_HASH-5.4.106 = cc873b2c39c1823d4bc4f6cde527943c8cfd28ae94cb517804b0f9679359c8db -LINUX_KERNEL_HASH-5.10.24 = c6dcd04e5893c5d68b637188f904528e91f28d790cd49cf8a7fb817423bd763f +LINUX_KERNEL_HASH-5.10.25 = 930ae76b9a3b64b98802849aca332d17a706f20595de21e1ae729b55ee461add remove_uri_prefix=$(subst git://,,$(subst http://,,$(subst https://,,$(1)))) sanitize_uri=$(call qstrip,$(subst @,_,$(subst :,_,$(subst .,_,$(subst -,_,$(subst /,_,$(1))))))) diff --git a/target/linux/bmips/patches-5.10/050-v5.13-net-dsa-b53-support-legacy-tags.patch b/target/linux/bmips/patches-5.10/050-v5.13-net-dsa-b53-support-legacy-tags.patch index 59a7217663..269c2895af 100644 --- a/target/linux/bmips/patches-5.10/050-v5.13-net-dsa-b53-support-legacy-tags.patch +++ b/target/linux/bmips/patches-5.10/050-v5.13-net-dsa-b53-support-legacy-tags.patch @@ -28,7 +28,7 @@ Signed-off-by: David S. Miller This driver adds support for Broadcom managed switch chips. It supports --- a/drivers/net/dsa/b53/b53_common.c +++ b/drivers/net/dsa/b53/b53_common.c -@@ -2010,15 +2010,17 @@ enum dsa_tag_protocol b53_get_tag_protoc +@@ -2028,15 +2028,17 @@ enum dsa_tag_protocol b53_get_tag_protoc { struct b53_device *dev = ds->priv; diff --git a/target/linux/bmips/patches-5.10/505-net-dsa-b53-add-support-for-BCM63xx-RGMIIs.patch b/target/linux/bmips/patches-5.10/505-net-dsa-b53-add-support-for-BCM63xx-RGMIIs.patch index f5bc8807b1..0b69f45360 100644 --- a/target/linux/bmips/patches-5.10/505-net-dsa-b53-add-support-for-BCM63xx-RGMIIs.patch +++ b/target/linux/bmips/patches-5.10/505-net-dsa-b53-add-support-for-BCM63xx-RGMIIs.patch @@ -13,7 +13,7 @@ Signed-off-by: Álvaro Fernández Rojas --- a/drivers/net/dsa/b53/b53_common.c +++ b/drivers/net/dsa/b53/b53_common.c -@@ -1140,6 +1140,36 @@ static void b53_force_port_config(struct +@@ -1155,6 +1155,36 @@ static void b53_force_port_config(struct b53_write8(dev, B53_CTRL_PAGE, off, reg); } @@ -50,7 +50,7 @@ Signed-off-by: Álvaro Fernández Rojas static void b53_adjust_link(struct dsa_switch *ds, int port, struct phy_device *phydev) { -@@ -1166,6 +1196,9 @@ static void b53_adjust_link(struct dsa_s +@@ -1181,6 +1211,9 @@ static void b53_adjust_link(struct dsa_s tx_pause, rx_pause); b53_force_link(dev, port, phydev->link); @@ -60,7 +60,7 @@ Signed-off-by: Álvaro Fernández Rojas if (is531x5(dev) && phy_interface_is_rgmii(phydev)) { if (port == 8) off = B53_RGMII_CTRL_IMP; -@@ -1358,6 +1391,9 @@ void b53_phylink_mac_link_up(struct dsa_ +@@ -1373,6 +1406,9 @@ void b53_phylink_mac_link_up(struct dsa_ { struct b53_device *dev = ds->priv; diff --git a/target/linux/generic/hack-5.10/902-debloat_proc.patch b/target/linux/generic/hack-5.10/902-debloat_proc.patch index 5a6d7d058e..3208e5554f 100644 --- a/target/linux/generic/hack-5.10/902-debloat_proc.patch +++ b/target/linux/generic/hack-5.10/902-debloat_proc.patch @@ -29,7 +29,7 @@ Signed-off-by: Felix Fietkau --- a/fs/locks.c +++ b/fs/locks.c -@@ -2996,6 +2996,8 @@ static const struct seq_operations locks +@@ -2993,6 +2993,8 @@ static const struct seq_operations locks static int __init proc_locks_init(void) { From 22d2c972c47466ba9e1a59aefeca8d9efa08b335 Mon Sep 17 00:00:00 2001 From: Kevin Darbyshire-Bryant Date: Tue, 14 Jan 2020 22:19:06 +0000 Subject: [PATCH 10/31] kernel: drop apu2 reboot patch This patch really annoys me, either it needs to go upstream or be dropped, so it's going to be dropped here. Checking drivers/platform/x86/pcengines-apuv2.c it also appears to be incomplete since it mentions different dmi board names depending on bios version. /* APU2 w/ legacy BIOS < 4.0.8 */ is 'APU2' /* APU2 w/ legacy BIOS >= 4.0.8 */ is 'apu2' /* APU2 w/ mainline BIOS */ is 'PC Engines apu2' So the patch, if applicable at all, only 'works' for legacy BIOS >= 4.0.8 My APU2 on mainline BIOS reboots fine without this patch. So let's see if anyone screams and when they do question why legacy bios. If patch DOES need to be re-introduced then it needs to go upstream first. Signed-off-by: Kevin Darbyshire-Bryant --- .../200-pcengines-apu2-reboot.patch | 19 ------------------- .../200-pcengines-apu2-reboot.patch | 19 ------------------- 2 files changed, 38 deletions(-) delete mode 100644 target/linux/x86/patches-5.10/200-pcengines-apu2-reboot.patch delete mode 100644 target/linux/x86/patches-5.4/200-pcengines-apu2-reboot.patch diff --git a/target/linux/x86/patches-5.10/200-pcengines-apu2-reboot.patch b/target/linux/x86/patches-5.10/200-pcengines-apu2-reboot.patch deleted file mode 100644 index 742b6d6ad5..0000000000 --- a/target/linux/x86/patches-5.10/200-pcengines-apu2-reboot.patch +++ /dev/null @@ -1,19 +0,0 @@ ---- a/arch/x86/kernel/reboot.c -+++ b/arch/x86/kernel/reboot.c -@@ -486,6 +486,16 @@ static const struct dmi_system_id reboot - }, - }, - -+ /* PC Engines */ -+ { /* Handle problems with rebooting on PC Engines apu2 */ -+ .callback = set_pci_reboot, -+ .ident = "PC Engines apu2", -+ .matches = { -+ DMI_MATCH(DMI_BOARD_VENDOR, "PC Engines"), -+ DMI_MATCH(DMI_BOARD_NAME, "apu2"), -+ }, -+ }, -+ - /* Sony */ - { /* Handle problems with rebooting on Sony VGN-Z540N */ - .callback = set_bios_reboot, diff --git a/target/linux/x86/patches-5.4/200-pcengines-apu2-reboot.patch b/target/linux/x86/patches-5.4/200-pcengines-apu2-reboot.patch deleted file mode 100644 index 742b6d6ad5..0000000000 --- a/target/linux/x86/patches-5.4/200-pcengines-apu2-reboot.patch +++ /dev/null @@ -1,19 +0,0 @@ ---- a/arch/x86/kernel/reboot.c -+++ b/arch/x86/kernel/reboot.c -@@ -486,6 +486,16 @@ static const struct dmi_system_id reboot - }, - }, - -+ /* PC Engines */ -+ { /* Handle problems with rebooting on PC Engines apu2 */ -+ .callback = set_pci_reboot, -+ .ident = "PC Engines apu2", -+ .matches = { -+ DMI_MATCH(DMI_BOARD_VENDOR, "PC Engines"), -+ DMI_MATCH(DMI_BOARD_NAME, "apu2"), -+ }, -+ }, -+ - /* Sony */ - { /* Handle problems with rebooting on Sony VGN-Z540N */ - .callback = set_bios_reboot, From bd47189602f8dce21297669424b0033c7d03bce7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Wed, 24 Mar 2021 14:02:56 +0100 Subject: [PATCH 11/31] kernel: backport ehci overcurrent patches MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These patches have been accepted for v5.13. Signed-off-by: Álvaro Fernández Rojas --- ...I-controller-does-not-support-overcu.patch | 4 +- ...I-controller-does-not-support-overcu.patch | 4 +- ...t-generic-ehci-ignore-oc-device-tree.patch | 12 ------ ...ious-flag-to-disable-overcurrent-ch.patch} | 37 ++++++++++++------- ...-platform-add-spurious_oc-DT-support.patch | 31 ++++++++++++++++ ...ious-flag-to-disable-overcurrent-ch.patch} | 37 ++++++++++++------- ...-platform-add-spurious_oc-DT-support.patch | 31 ++++++++++++++++ 7 files changed, 112 insertions(+), 44 deletions(-) delete mode 100644 target/linux/bmips/patches-5.10/300-usb-host-generic-ehci-ignore-oc-device-tree.patch rename target/linux/generic/{pending-5.10/110-ehci_hcd_ignore_oc.patch => backport-5.10/810-v5.13-usb-ehci-add-spurious-flag-to-disable-overcurrent-ch.patch} (69%) create mode 100644 target/linux/generic/backport-5.10/811-v5.13-usb-host-ehci-platform-add-spurious_oc-DT-support.patch rename target/linux/generic/{pending-5.4/110-ehci_hcd_ignore_oc.patch => backport-5.4/850-v5.13-usb-ehci-add-spurious-flag-to-disable-overcurrent-ch.patch} (69%) create mode 100644 target/linux/generic/backport-5.4/851-v5.13-usb-host-ehci-platform-add-spurious_oc-DT-support.patch diff --git a/target/linux/bcm63xx/patches-5.10/110-MIPS-BCM63XX-EHCI-controller-does-not-support-overcu.patch b/target/linux/bcm63xx/patches-5.10/110-MIPS-BCM63XX-EHCI-controller-does-not-support-overcu.patch index 6d91129932..5822166485 100644 --- a/target/linux/bcm63xx/patches-5.10/110-MIPS-BCM63XX-EHCI-controller-does-not-support-overcu.patch +++ b/target/linux/bcm63xx/patches-5.10/110-MIPS-BCM63XX-EHCI-controller-does-not-support-overcu.patch @@ -4,7 +4,7 @@ Date: Mon, 28 Jan 2013 20:06:30 +0100 Subject: [PATCH 12/12] MIPS: BCM63XX: EHCI controller does not support overcurrent -This patch sets the ignore_oc flag for the BCM63XX EHCI controller as it +This patch sets the spurious_oc flag for the BCM63XX EHCI controller as it does not support proper overcurrent reporting. Signed-off-by: Florian Fainelli @@ -18,7 +18,7 @@ Signed-off-by: Florian Fainelli static struct usb_ehci_pdata bcm63xx_ehci_pdata = { .big_endian_desc = 1, .big_endian_mmio = 1, -+ .ignore_oc = 1, ++ .spurious_oc = 1, .power_on = bcm63xx_ehci_power_on, .power_off = bcm63xx_ehci_power_off, .power_suspend = bcm63xx_ehci_power_off, diff --git a/target/linux/bcm63xx/patches-5.4/110-MIPS-BCM63XX-EHCI-controller-does-not-support-overcu.patch b/target/linux/bcm63xx/patches-5.4/110-MIPS-BCM63XX-EHCI-controller-does-not-support-overcu.patch index 6d91129932..5822166485 100644 --- a/target/linux/bcm63xx/patches-5.4/110-MIPS-BCM63XX-EHCI-controller-does-not-support-overcu.patch +++ b/target/linux/bcm63xx/patches-5.4/110-MIPS-BCM63XX-EHCI-controller-does-not-support-overcu.patch @@ -4,7 +4,7 @@ Date: Mon, 28 Jan 2013 20:06:30 +0100 Subject: [PATCH 12/12] MIPS: BCM63XX: EHCI controller does not support overcurrent -This patch sets the ignore_oc flag for the BCM63XX EHCI controller as it +This patch sets the spurious_oc flag for the BCM63XX EHCI controller as it does not support proper overcurrent reporting. Signed-off-by: Florian Fainelli @@ -18,7 +18,7 @@ Signed-off-by: Florian Fainelli static struct usb_ehci_pdata bcm63xx_ehci_pdata = { .big_endian_desc = 1, .big_endian_mmio = 1, -+ .ignore_oc = 1, ++ .spurious_oc = 1, .power_on = bcm63xx_ehci_power_on, .power_off = bcm63xx_ehci_power_off, .power_suspend = bcm63xx_ehci_power_off, diff --git a/target/linux/bmips/patches-5.10/300-usb-host-generic-ehci-ignore-oc-device-tree.patch b/target/linux/bmips/patches-5.10/300-usb-host-generic-ehci-ignore-oc-device-tree.patch deleted file mode 100644 index e65dbd9027..0000000000 --- a/target/linux/bmips/patches-5.10/300-usb-host-generic-ehci-ignore-oc-device-tree.patch +++ /dev/null @@ -1,12 +0,0 @@ ---- a/drivers/usb/host/ehci-platform.c -+++ b/drivers/usb/host/ehci-platform.c -@@ -286,6 +286,9 @@ static int ehci_platform_probe(struct pl - if (of_property_read_bool(dev->dev.of_node, "big-endian")) - ehci->big_endian_mmio = ehci->big_endian_desc = 1; - -+ if (of_property_read_bool(dev->dev.of_node, "ignore-oc")) -+ ehci->ignore_oc = 1; -+ - if (of_property_read_bool(dev->dev.of_node, - "needs-reset-on-resume")) - priv->reset_on_resume = true; diff --git a/target/linux/generic/pending-5.10/110-ehci_hcd_ignore_oc.patch b/target/linux/generic/backport-5.10/810-v5.13-usb-ehci-add-spurious-flag-to-disable-overcurrent-ch.patch similarity index 69% rename from target/linux/generic/pending-5.10/110-ehci_hcd_ignore_oc.patch rename to target/linux/generic/backport-5.10/810-v5.13-usb-ehci-add-spurious-flag-to-disable-overcurrent-ch.patch index 138d4fa1c5..8f2021a0fc 100644 --- a/target/linux/generic/pending-5.10/110-ehci_hcd_ignore_oc.patch +++ b/target/linux/generic/backport-5.10/810-v5.13-usb-ehci-add-spurious-flag-to-disable-overcurrent-ch.patch @@ -1,5 +1,11 @@ +From 2d5ba37461013253d2ff0a3641b727fd32ea97a9 Mon Sep 17 00:00:00 2001 From: Florian Fainelli -Subject: USB: EHCI: add ignore_oc flag to disable overcurrent checking +Date: Tue, 23 Feb 2021 18:44:53 +0100 +Subject: [PATCH 1/3] usb: ehci: add spurious flag to disable overcurrent + checking +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit This patch adds an ignore_oc flag which can be set by EHCI controller not supporting or wanting to disable overcurrent checking. The EHCI @@ -7,13 +13,16 @@ platform data in include/linux/usb/ehci_pdriver.h is also augmented to take advantage of this new flag. Signed-off-by: Florian Fainelli +Signed-off-by: Álvaro Fernández Rojas +Link: https://lore.kernel.org/r/20210223174455.1378-2-noltari@gmail.com +Signed-off-by: Greg Kroah-Hartman --- - drivers/usb/host/ehci-hcd.c | 2 +- - drivers/usb/host/ehci-hub.c | 4 ++-- - drivers/usb/host/ehci-platform.c | 1 + - drivers/usb/host/ehci.h | 1 + - include/linux/usb/ehci_pdriver.h | 1 + - 5 files changed, 6 insertions(+), 3 deletions(-) + drivers/usb/host/ehci-hcd.c | 2 +- + drivers/usb/host/ehci-hub.c | 4 ++-- + drivers/usb/host/ehci-platform.c | 2 ++ + drivers/usb/host/ehci.h | 1 + + include/linux/usb/ehci_pdriver.h | 1 + + 5 files changed, 7 insertions(+), 3 deletions(-) --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -22,7 +31,7 @@ Signed-off-by: Florian Fainelli ((ehci->sbrn & 0xf0)>>4), (ehci->sbrn & 0x0f), temp >> 8, temp & 0xff, - ignore_oc ? ", overcurrent ignored" : ""); -+ (ignore_oc || ehci->ignore_oc) ? ", overcurrent ignored" : ""); ++ (ignore_oc || ehci->spurious_oc) ? ", overcurrent ignored" : ""); ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable); /* Turn On Interrupts */ @@ -33,7 +42,7 @@ Signed-off-by: Florian Fainelli * PORT_POWER; that's surprising, but maybe within-spec. */ - if (!ignore_oc) -+ if (!ignore_oc && !ehci->ignore_oc) ++ if (!ignore_oc && !ehci->spurious_oc) mask = PORT_CSC | PORT_PEC | PORT_OCC; else mask = PORT_CSC | PORT_PEC; @@ -42,7 +51,7 @@ Signed-off-by: Florian Fainelli status |= USB_PORT_STAT_C_ENABLE << 16; - if ((temp & PORT_OCC) && !ignore_oc){ -+ if ((temp & PORT_OCC) && (!ignore_oc && !ehci->ignore_oc)){ ++ if ((temp & PORT_OCC) && (!ignore_oc && !ehci->spurious_oc)){ status |= USB_PORT_STAT_C_OVERCURRENT << 16; /* @@ -52,8 +61,8 @@ Signed-off-by: Florian Fainelli hcd->has_tt = 1; if (pdata->reset_on_resume) priv->reset_on_resume = true; -+ if (pdata->ignore_oc) -+ ehci->ignore_oc = 1; ++ if (pdata->spurious_oc) ++ ehci->spurious_oc = 1; #ifndef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO if (ehci->big_endian_mmio) { @@ -63,7 +72,7 @@ Signed-off-by: Florian Fainelli unsigned frame_index_bug:1; /* MosChip (AKA NetMos) */ unsigned need_oc_pp_cycle:1; /* MPC834X port power */ unsigned imx28_write_fix:1; /* For Freescale i.MX28 */ -+ unsigned ignore_oc:1; ++ unsigned spurious_oc:1; /* required for usb32 quirk */ #define OHCI_CTRL_HCFS (3 << 6) @@ -73,7 +82,7 @@ Signed-off-by: Florian Fainelli unsigned no_io_watchdog:1; unsigned reset_on_resume:1; unsigned dma_mask_64:1; -+ unsigned ignore_oc:1; ++ unsigned spurious_oc:1; /* Turn on all power and clocks */ int (*power_on)(struct platform_device *pdev); diff --git a/target/linux/generic/backport-5.10/811-v5.13-usb-host-ehci-platform-add-spurious_oc-DT-support.patch b/target/linux/generic/backport-5.10/811-v5.13-usb-host-ehci-platform-add-spurious_oc-DT-support.patch new file mode 100644 index 0000000000..0094d47718 --- /dev/null +++ b/target/linux/generic/backport-5.10/811-v5.13-usb-host-ehci-platform-add-spurious_oc-DT-support.patch @@ -0,0 +1,31 @@ +From 4da57dbbffdfa7fe4e2b70b047fc5ff95ff25a3d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= +Date: Tue, 23 Feb 2021 18:44:55 +0100 +Subject: [PATCH 3/3] usb: host: ehci-platform: add spurious_oc DT support +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Over-current reporting isn't supported on some platforms such as bcm63xx. +These devices will incorrectly report over-current if this flag isn't properly +activated. + +Signed-off-by: Álvaro Fernández Rojas +Link: https://lore.kernel.org/r/20210223174455.1378-4-noltari@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/host/ehci-platform.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/usb/host/ehci-platform.c ++++ b/drivers/usb/host/ehci-platform.c +@@ -286,6 +286,9 @@ static int ehci_platform_probe(struct pl + if (of_property_read_bool(dev->dev.of_node, "big-endian")) + ehci->big_endian_mmio = ehci->big_endian_desc = 1; + ++ if (of_property_read_bool(dev->dev.of_node, "spurious-oc")) ++ ehci->spurious_oc = 1; ++ + if (of_property_read_bool(dev->dev.of_node, + "needs-reset-on-resume")) + priv->reset_on_resume = true; diff --git a/target/linux/generic/pending-5.4/110-ehci_hcd_ignore_oc.patch b/target/linux/generic/backport-5.4/850-v5.13-usb-ehci-add-spurious-flag-to-disable-overcurrent-ch.patch similarity index 69% rename from target/linux/generic/pending-5.4/110-ehci_hcd_ignore_oc.patch rename to target/linux/generic/backport-5.4/850-v5.13-usb-ehci-add-spurious-flag-to-disable-overcurrent-ch.patch index ce583ceac5..bda1d1df36 100644 --- a/target/linux/generic/pending-5.4/110-ehci_hcd_ignore_oc.patch +++ b/target/linux/generic/backport-5.4/850-v5.13-usb-ehci-add-spurious-flag-to-disable-overcurrent-ch.patch @@ -1,5 +1,11 @@ +From 2d5ba37461013253d2ff0a3641b727fd32ea97a9 Mon Sep 17 00:00:00 2001 From: Florian Fainelli -Subject: USB: EHCI: add ignore_oc flag to disable overcurrent checking +Date: Tue, 23 Feb 2021 18:44:53 +0100 +Subject: [PATCH 1/3] usb: ehci: add spurious flag to disable overcurrent + checking +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit This patch adds an ignore_oc flag which can be set by EHCI controller not supporting or wanting to disable overcurrent checking. The EHCI @@ -7,13 +13,16 @@ platform data in include/linux/usb/ehci_pdriver.h is also augmented to take advantage of this new flag. Signed-off-by: Florian Fainelli +Signed-off-by: Álvaro Fernández Rojas +Link: https://lore.kernel.org/r/20210223174455.1378-2-noltari@gmail.com +Signed-off-by: Greg Kroah-Hartman --- - drivers/usb/host/ehci-hcd.c | 2 +- - drivers/usb/host/ehci-hub.c | 4 ++-- - drivers/usb/host/ehci-platform.c | 1 + - drivers/usb/host/ehci.h | 1 + - include/linux/usb/ehci_pdriver.h | 1 + - 5 files changed, 6 insertions(+), 3 deletions(-) + drivers/usb/host/ehci-hcd.c | 2 +- + drivers/usb/host/ehci-hub.c | 4 ++-- + drivers/usb/host/ehci-platform.c | 2 ++ + drivers/usb/host/ehci.h | 1 + + include/linux/usb/ehci_pdriver.h | 1 + + 5 files changed, 7 insertions(+), 3 deletions(-) --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -22,7 +31,7 @@ Signed-off-by: Florian Fainelli ((ehci->sbrn & 0xf0)>>4), (ehci->sbrn & 0x0f), temp >> 8, temp & 0xff, - ignore_oc ? ", overcurrent ignored" : ""); -+ (ignore_oc || ehci->ignore_oc) ? ", overcurrent ignored" : ""); ++ (ignore_oc || ehci->spurious_oc) ? ", overcurrent ignored" : ""); ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable); /* Turn On Interrupts */ @@ -33,7 +42,7 @@ Signed-off-by: Florian Fainelli * PORT_POWER; that's surprising, but maybe within-spec. */ - if (!ignore_oc) -+ if (!ignore_oc && !ehci->ignore_oc) ++ if (!ignore_oc && !ehci->spurious_oc) mask = PORT_CSC | PORT_PEC | PORT_OCC; else mask = PORT_CSC | PORT_PEC; @@ -42,7 +51,7 @@ Signed-off-by: Florian Fainelli status |= USB_PORT_STAT_C_ENABLE << 16; - if ((temp & PORT_OCC) && !ignore_oc){ -+ if ((temp & PORT_OCC) && (!ignore_oc && !ehci->ignore_oc)){ ++ if ((temp & PORT_OCC) && (!ignore_oc && !ehci->spurious_oc)){ status |= USB_PORT_STAT_C_OVERCURRENT << 16; /* @@ -52,8 +61,8 @@ Signed-off-by: Florian Fainelli hcd->has_tt = 1; if (pdata->reset_on_resume) priv->reset_on_resume = true; -+ if (pdata->ignore_oc) -+ ehci->ignore_oc = 1; ++ if (pdata->spurious_oc) ++ ehci->spurious_oc = 1; #ifndef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO if (ehci->big_endian_mmio) { @@ -63,7 +72,7 @@ Signed-off-by: Florian Fainelli unsigned frame_index_bug:1; /* MosChip (AKA NetMos) */ unsigned need_oc_pp_cycle:1; /* MPC834X port power */ unsigned imx28_write_fix:1; /* For Freescale i.MX28 */ -+ unsigned ignore_oc:1; ++ unsigned spurious_oc:1; /* required for usb32 quirk */ #define OHCI_CTRL_HCFS (3 << 6) @@ -73,7 +82,7 @@ Signed-off-by: Florian Fainelli unsigned no_io_watchdog:1; unsigned reset_on_resume:1; unsigned dma_mask_64:1; -+ unsigned ignore_oc:1; ++ unsigned spurious_oc:1; /* Turn on all power and clocks */ int (*power_on)(struct platform_device *pdev); diff --git a/target/linux/generic/backport-5.4/851-v5.13-usb-host-ehci-platform-add-spurious_oc-DT-support.patch b/target/linux/generic/backport-5.4/851-v5.13-usb-host-ehci-platform-add-spurious_oc-DT-support.patch new file mode 100644 index 0000000000..6faefeb79c --- /dev/null +++ b/target/linux/generic/backport-5.4/851-v5.13-usb-host-ehci-platform-add-spurious_oc-DT-support.patch @@ -0,0 +1,31 @@ +From 4da57dbbffdfa7fe4e2b70b047fc5ff95ff25a3d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= +Date: Tue, 23 Feb 2021 18:44:55 +0100 +Subject: [PATCH 3/3] usb: host: ehci-platform: add spurious_oc DT support +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Over-current reporting isn't supported on some platforms such as bcm63xx. +These devices will incorrectly report over-current if this flag isn't properly +activated. + +Signed-off-by: Álvaro Fernández Rojas +Link: https://lore.kernel.org/r/20210223174455.1378-4-noltari@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/host/ehci-platform.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/usb/host/ehci-platform.c ++++ b/drivers/usb/host/ehci-platform.c +@@ -278,6 +278,9 @@ static int ehci_platform_probe(struct pl + if (of_property_read_bool(dev->dev.of_node, "big-endian")) + ehci->big_endian_mmio = ehci->big_endian_desc = 1; + ++ if (of_property_read_bool(dev->dev.of_node, "spurious-oc")) ++ ehci->spurious_oc = 1; ++ + if (of_property_read_bool(dev->dev.of_node, + "needs-reset-on-resume")) + priv->reset_on_resume = true; From 4165e565d257ed318591f2bf5eca7a472052ec68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Wed, 24 Mar 2021 14:19:12 +0100 Subject: [PATCH 12/31] bmips: switch to upstream ehci overcurrent flag MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After backporting upstream ehci overcurrent patches we need to use spurious-oc instead of ignore-oc. Signed-off-by: Álvaro Fernández Rojas --- target/linux/bmips/dts/bcm6318.dtsi | 2 +- target/linux/bmips/dts/bcm63268.dtsi | 2 +- target/linux/bmips/dts/bcm6328.dtsi | 2 +- target/linux/bmips/dts/bcm6358.dtsi | 2 +- target/linux/bmips/dts/bcm6362.dtsi | 2 +- target/linux/bmips/dts/bcm6368.dtsi | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/target/linux/bmips/dts/bcm6318.dtsi b/target/linux/bmips/dts/bcm6318.dtsi index 9067db952e..6064c9ac4c 100644 --- a/target/linux/bmips/dts/bcm6318.dtsi +++ b/target/linux/bmips/dts/bcm6318.dtsi @@ -304,7 +304,7 @@ compatible = "brcm,bcm6318-ehci", "generic-ehci"; reg = <0x10005000 0x100>; big-endian; - ignore-oc; + spurious-oc; interrupt-parent = <&periph_intc>; interrupts = ; diff --git a/target/linux/bmips/dts/bcm63268.dtsi b/target/linux/bmips/dts/bcm63268.dtsi index 32cbbd7200..d71cef4ccd 100644 --- a/target/linux/bmips/dts/bcm63268.dtsi +++ b/target/linux/bmips/dts/bcm63268.dtsi @@ -396,7 +396,7 @@ compatible = "brcm,bcm63268-ehci", "generic-ehci"; reg = <0x10002500 0x100>; big-endian; - ignore-oc; + spurious-oc; interrupt-parent = <&periph_intc>; interrupts = ; diff --git a/target/linux/bmips/dts/bcm6328.dtsi b/target/linux/bmips/dts/bcm6328.dtsi index 76d7a257d4..6ca7e4d9a6 100644 --- a/target/linux/bmips/dts/bcm6328.dtsi +++ b/target/linux/bmips/dts/bcm6328.dtsi @@ -334,7 +334,7 @@ compatible = "brcm,bcm6328-ehci", "generic-ehci"; reg = <0x10002500 0x100>; big-endian; - ignore-oc; + spurious-oc; interrupt-parent = <&periph_intc>; interrupts = ; diff --git a/target/linux/bmips/dts/bcm6358.dtsi b/target/linux/bmips/dts/bcm6358.dtsi index fee9850059..3ebbf74613 100644 --- a/target/linux/bmips/dts/bcm6358.dtsi +++ b/target/linux/bmips/dts/bcm6358.dtsi @@ -309,7 +309,7 @@ compatible = "brcm,bcm6358-ehci", "generic-ehci"; reg = <0xfffe1300 0x100>; big-endian; - ignore-oc; + spurious-oc; interrupt-parent = <&periph_intc>; interrupts = ; diff --git a/target/linux/bmips/dts/bcm6362.dtsi b/target/linux/bmips/dts/bcm6362.dtsi index 1ae1522287..04df06c0db 100644 --- a/target/linux/bmips/dts/bcm6362.dtsi +++ b/target/linux/bmips/dts/bcm6362.dtsi @@ -431,7 +431,7 @@ compatible = "brcm,bcm6362-ehci", "generic-ehci"; reg = <0x10002500 0x100>; big-endian; - ignore-oc; + spurious-oc; interrupt-parent = <&periph_intc>; interrupts = ; diff --git a/target/linux/bmips/dts/bcm6368.dtsi b/target/linux/bmips/dts/bcm6368.dtsi index 9f59182517..afdf3c5dc0 100644 --- a/target/linux/bmips/dts/bcm6368.dtsi +++ b/target/linux/bmips/dts/bcm6368.dtsi @@ -446,7 +446,7 @@ compatible = "brcm,bcm6368-ehci", "generic-ehci"; reg = <0x10001500 0x100>; big-endian; - ignore-oc; + spurious-oc; interrupt-parent = <&periph_intc>; interrupts = ; From 5053593e667ff5d0d78573832d8969c7b6b5be47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Wed, 24 Mar 2021 14:49:46 +0100 Subject: [PATCH 13/31] bmips: reorganize patches MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reorder kernel patches after recent backports. Signed-off-by: Álvaro Fernández Rojas --- ...y.patch => 120-wdt-bcm7038-add-big-endian-compatibility.patch} | 0 ...=> 202-mips-bmips-disable-ARCH_HAS_SYNC_DMA_FOR_CPU_ALL.patch} | 0 ...> 500-net-broadcom-add-BCM6368-enetsw-controller-driver.patch} | 0 ...patch => 510-net-dsa-b53-add-support-for-BCM63xx-RGMIIs.patch} | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename target/linux/bmips/patches-5.10/{204-wdt-bcm7038-add-big-endian-compatibility.patch => 120-wdt-bcm7038-add-big-endian-compatibility.patch} (100%) rename target/linux/bmips/patches-5.10/{208-mips-bmips-disable-ARCH_HAS_SYNC_DMA_FOR_CPU_ALL.patch => 202-mips-bmips-disable-ARCH_HAS_SYNC_DMA_FOR_CPU_ALL.patch} (100%) rename target/linux/bmips/patches-5.10/{503-net-broadcom-add-BCM6368-enetsw-controller-driver.patch => 500-net-broadcom-add-BCM6368-enetsw-controller-driver.patch} (100%) rename target/linux/bmips/patches-5.10/{505-net-dsa-b53-add-support-for-BCM63xx-RGMIIs.patch => 510-net-dsa-b53-add-support-for-BCM63xx-RGMIIs.patch} (100%) diff --git a/target/linux/bmips/patches-5.10/204-wdt-bcm7038-add-big-endian-compatibility.patch b/target/linux/bmips/patches-5.10/120-wdt-bcm7038-add-big-endian-compatibility.patch similarity index 100% rename from target/linux/bmips/patches-5.10/204-wdt-bcm7038-add-big-endian-compatibility.patch rename to target/linux/bmips/patches-5.10/120-wdt-bcm7038-add-big-endian-compatibility.patch diff --git a/target/linux/bmips/patches-5.10/208-mips-bmips-disable-ARCH_HAS_SYNC_DMA_FOR_CPU_ALL.patch b/target/linux/bmips/patches-5.10/202-mips-bmips-disable-ARCH_HAS_SYNC_DMA_FOR_CPU_ALL.patch similarity index 100% rename from target/linux/bmips/patches-5.10/208-mips-bmips-disable-ARCH_HAS_SYNC_DMA_FOR_CPU_ALL.patch rename to target/linux/bmips/patches-5.10/202-mips-bmips-disable-ARCH_HAS_SYNC_DMA_FOR_CPU_ALL.patch diff --git a/target/linux/bmips/patches-5.10/503-net-broadcom-add-BCM6368-enetsw-controller-driver.patch b/target/linux/bmips/patches-5.10/500-net-broadcom-add-BCM6368-enetsw-controller-driver.patch similarity index 100% rename from target/linux/bmips/patches-5.10/503-net-broadcom-add-BCM6368-enetsw-controller-driver.patch rename to target/linux/bmips/patches-5.10/500-net-broadcom-add-BCM6368-enetsw-controller-driver.patch diff --git a/target/linux/bmips/patches-5.10/505-net-dsa-b53-add-support-for-BCM63xx-RGMIIs.patch b/target/linux/bmips/patches-5.10/510-net-dsa-b53-add-support-for-BCM63xx-RGMIIs.patch similarity index 100% rename from target/linux/bmips/patches-5.10/505-net-dsa-b53-add-support-for-BCM63xx-RGMIIs.patch rename to target/linux/bmips/patches-5.10/510-net-dsa-b53-add-support-for-BCM63xx-RGMIIs.patch From 13a23445f43fda28fcaa7458b860188139754ccb Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Wed, 24 Mar 2021 14:13:43 +0000 Subject: [PATCH 14/31] ucode: fix PKG_MIRROR_HASH Signed-off-by: Daniel Golle --- package/utils/ucode/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/utils/ucode/Makefile b/package/utils/ucode/Makefile index 64b6c7bcda..6fb9f73c3d 100644 --- a/package/utils/ucode/Makefile +++ b/package/utils/ucode/Makefile @@ -14,7 +14,7 @@ PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=https://github.com/jow-/ucode.git PKG_SOURCE_DATE:=2021-03-19 PKG_SOURCE_VERSION:=4a5b9010ccc56fdf288fe758023af445feb93fad -PKG_MIRROR_HASH:=145a2ce69e14cae9b448de85b94c7a817ba3aea04b1611399186ad36fb88958e +PKG_MIRROR_HASH:=2d15fe2f51ebdeae532a2e8130689400cf2364876e737cfbb1bf9c045719acf1 PKG_MAINTAINER:=Jo-Philipp Wich PKG_LICENSE:=ISC From 9b3aaf1cdb873cc2a7b2f2ef4e72ddb716afba38 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Wed, 24 Mar 2021 09:47:12 +0000 Subject: [PATCH 15/31] mwlwifi: add PKG_FLAGS:=nonshared This should fix the problem of mwlwifi-firmware-* not being found when using the ImageBuilder. Signed-off-by: Daniel Golle --- package/kernel/mwlwifi/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/package/kernel/mwlwifi/Makefile b/package/kernel/mwlwifi/Makefile index 648c826ccb..eb986dca03 100644 --- a/package/kernel/mwlwifi/Makefile +++ b/package/kernel/mwlwifi/Makefile @@ -21,6 +21,7 @@ PKG_MIRROR_HASH:=0eda0e774a87e58e611d6436350e1cf2be3de50fddde334909a07a15b0c9862 PKG_MAINTAINER:=Imre Kaloz PKG_BUILD_PARALLEL:=1 +PKG_FLAGS:=nonshared include $(INCLUDE_DIR)/kernel.mk include $(INCLUDE_DIR)/package.mk From ca2ef4a79f4e93d8b5eb9441f33e6cc9b0a6e39c Mon Sep 17 00:00:00 2001 From: Oskari Lemmela Date: Sun, 21 Mar 2021 10:58:10 +0200 Subject: [PATCH 16/31] build: artifacts: add dependency for built images Add possibility to use images and initramfs in artifacts. Signed-off-by: Oskari Lemmela Signed-off-by: Daniel Golle --- include/image.mk | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/include/image.mk b/include/image.mk index 29df0938bc..8b7b2b9740 100644 --- a/include/image.mk +++ b/include/image.mk @@ -478,6 +478,7 @@ define Device/Build/initramfs $$(if $$(CONFIG_JSON_OVERVIEW_IMAGE_INFO), $(BUILD_DIR)/json_info_files/$$(KERNEL_INITRAMFS_IMAGE).json,)) $(KDIR)/$$(KERNEL_INITRAMFS_NAME):: image_prepare + $(1)-images: $(BIN_DIR)/$$(KERNEL_INITRAMFS_IMAGE) $(BIN_DIR)/$$(KERNEL_INITRAMFS_IMAGE): $(KDIR)/tmp/$$(KERNEL_INITRAMFS_IMAGE) cp $$^ $$@ @@ -570,6 +571,7 @@ define Device/Build/image $(BUILD_DIR)/json_info_files/$(call DEVICE_IMG_NAME,$(1),$(2)).json, \ $(BIN_DIR)/$(call DEVICE_IMG_NAME,$(1),$(2))$$(GZ_SUFFIX)) $(eval $(call Device/Export,$(KDIR)/tmp/$(call DEVICE_IMG_NAME,$(1),$(2)),$(1))) + $(3)-images: $(BIN_DIR)/$(call DEVICE_IMG_NAME,$(1),$(2))$$(GZ_SUFFIX) ROOTFS/$(1)/$(3) := \ $(KDIR)/root.$(1)$$(strip \ @@ -628,7 +630,7 @@ endef define Device/Build/artifact $$(_TARGET): $(BIN_DIR)/$(DEVICE_IMG_PREFIX)-$(1) $(eval $(call Device/Export,$(KDIR)/tmp/$(DEVICE_IMG_PREFIX)-$(1))) - $(KDIR)/tmp/$(DEVICE_IMG_PREFIX)-$(1): $$(KDIR_KERNEL_IMAGE) + $(KDIR)/tmp/$(DEVICE_IMG_PREFIX)-$(1): $$(KDIR_KERNEL_IMAGE) $(2)-images @rm -f $$@ $$(call concat_cmd,$(ARTIFACT/$(1))) @@ -651,7 +653,7 @@ define Device/Build $$(call Device/Build/image,$$(fs),$$(image),$(1))))) $$(eval $$(foreach artifact,$$(ARTIFACTS), \ - $$(call Device/Build/artifact,$$(artifact)))) + $$(call Device/Build/artifact,$$(artifact),$(1)))) endef From 8f89b1ab0fef81c85925c88e99a557e91e575aa3 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Wed, 24 Mar 2021 13:34:13 +0000 Subject: [PATCH 17/31] image: add 'append-image' build command Commit 7ce1d9ce09 ("build: artifacts add dependency for built images") now makes sure that sysupgrade and initramfs images are available at the stage that artifacts are created. Allow making use of that with a new build command 'append-image' to be used in artifacts. See the next commit for an example. Signed-off-by: Daniel Golle --- include/image-commands.mk | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/image-commands.mk b/include/image-commands.mk index 684646e233..ec4f9624f5 100644 --- a/include/image-commands.mk +++ b/include/image-commands.mk @@ -27,6 +27,10 @@ define Build/append-kernel dd if=$(IMAGE_KERNEL) >> $@ endef +define Build/append-image + dd if=$(BIN_DIR)/$(IMG_PREFIX)$(if $(PROFILE_SANITIZED),-$(PROFILE_SANITIZED))-$(1) >> $@ +endef + compat_version=$(if $(DEVICE_COMPAT_VERSION),$(DEVICE_COMPAT_VERSION),1.0) json_quote=$(subst ','\'',$(subst ",\",$(1))) #")') From 6f5cd3bdcfce693c7f5f630043b4b5be19e0c592 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Wed, 24 Mar 2021 13:44:52 +0000 Subject: [PATCH 18/31] mediatek: generate complete sdcard image for BPi-R64 Populate the recovery and production partitions of the generated sdcard image for the Bananapi BPi-R64. Signed-off-by: Daniel Golle --- target/linux/mediatek/image/mt7622.mk | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/target/linux/mediatek/image/mt7622.mk b/target/linux/mediatek/image/mt7622.mk index 88d71600b2..143db964db 100644 --- a/target/linux/mediatek/image/mt7622.mk +++ b/target/linux/mediatek/image/mt7622.mk @@ -75,12 +75,17 @@ define Device/bananapi_bpi-r64 DEVICE_DTS := mt7622-bananapi-bpi-r64 DEVICE_DTS_OVERLAY := mt7622-bananapi-bpi-r64-pcie1 mt7622-bananapi-bpi-r64-sata DEVICE_PACKAGES := kmod-ata-ahci-mtk kmod-btmtkuart kmod-usb3 e2fsprogs mkf2fs f2fsck - ARTIFACTS := sdcard.img + ARTIFACTS := sdcard.img.gz IMAGES := sysupgrade.itb KERNEL_INITRAMFS_SUFFIX := -recovery.itb - ARTIFACT/sdcard.img := mt7622-gpt sdmmc | pad-to 128k | mt7622-gpt emmc | pad-to 256k |\ - bl2 emmc-2ddr | pad-to 512k | bl2 sdmmc-2ddr | pad-to 1024k | bl31-uboot bananapi_bpi-r64-emmc | pad-to 2048k |\ - bl31-uboot bananapi_bpi-r64-sdmmc | pad-to 6144k + ARTIFACT/sdcard.img.gz := mt7622-gpt sdmmc |\ + pad-to 128k | mt7622-gpt emmc |\ + pad-to 256k | bl2 emmc-2ddr |\ + pad-to 512k | bl2 sdmmc-2ddr |\ + pad-to 1024k | bl31-uboot bananapi_bpi-r64-emmc |\ + pad-to 2048k | bl31-uboot bananapi_bpi-r64-sdmmc |\ + pad-to 6144k | append-image initramfs-recovery.itb |\ + pad-to 40960k | append-image squashfs-sysupgrade.itb | gzip KERNEL := kernel-bin | gzip KERNEL_INITRAMFS := kernel-bin | lzma | fit lzma $$(DTS_DIR)/$$(DEVICE_DTS).dtb with-initrd | pad-to 128k IMAGE/sysupgrade.itb := append-kernel | fit gzip $$(DTS_DIR)/$$(DEVICE_DTS).dtb external-static-with-rootfs | append-metadata From 1ff7569387f69550e8a9356a109a875e4fdb4412 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Wed, 24 Mar 2021 17:29:30 +0100 Subject: [PATCH 19/31] firmware-utils: bcm4908img: name fields & values MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Less magic numbers Signed-off-by: Rafał Miłecki --- tools/firmware-utils/src/bcm4908img.c | 30 ++++++++++++++++++++------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/tools/firmware-utils/src/bcm4908img.c b/tools/firmware-utils/src/bcm4908img.c index 86a187b146..cb1913fdb1 100644 --- a/tools/firmware-utils/src/bcm4908img.c +++ b/tools/firmware-utils/src/bcm4908img.c @@ -27,12 +27,26 @@ #error "Unsupported endianness" #endif +#define WFI_VERSION 0x00005732 +#define WFI_VERSION_NAND_1MB_DATA 0x00005731 + +#define WFI_NOR_FLASH 1 +#define WFI_NAND16_FLASH 2 +#define WFI_NAND128_FLASH 3 +#define WFI_NAND256_FLASH 4 +#define WFI_NAND512_FLASH 5 +#define WFI_NAND1024_FLASH 6 +#define WFI_NAND2048_FLASH 7 + +#define WFI_FLAG_HAS_PMC 0x1 +#define WFI_FLAG_SUPPORTS_BTRM 0x2 + struct bcm4908img_tail { uint32_t crc32; - uint32_t unk1; - uint32_t family; - uint32_t unk2; - uint32_t unk3; + uint32_t version; + uint32_t chip_id; + uint32_t flash_type; + uint32_t flags; }; char *pathname; @@ -272,10 +286,10 @@ static ssize_t bcm4908img_create_align(FILE *trx, size_t cur_offset, size_t alig static int bcm4908img_create(int argc, char **argv) { struct bcm4908img_tail tail = { - .unk1 = cpu_to_le32(0x5732), - .family = cpu_to_le32(0x4908), - .unk2 = cpu_to_le32(0x03), - .unk3 = cpu_to_le32(0x02), + .version = cpu_to_le32(WFI_VERSION), + .chip_id = cpu_to_le32(0x4908), + .flash_type = cpu_to_le32(WFI_NAND128_FLASH), + .flags = cpu_to_le32(WFI_FLAG_SUPPORTS_BTRM), }; uint32_t crc32 = 0xffffffff; size_t cur_offset = 0; From 6dd727ac24fa36ac3f23e9a5cf6781a7d1c6b797 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Wed, 24 Mar 2021 18:20:13 +0100 Subject: [PATCH 20/31] kernel: create bootfs partition when parsing on BCM4908 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's helpful for accessing booting data (DTS, kernel, etc.). It has to be used carefully as CFE's JFFS2 support is quite dumb. It doesn't recognize deleted files and has problems handling 0 inode. Signed-off-by: Rafał Miłecki --- .../drivers/mtd/mtdsplit/mtdsplit_cfe_bootfs.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_cfe_bootfs.c b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_cfe_bootfs.c index 5c8a5e1b9b..a3474c9dc2 100644 --- a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_cfe_bootfs.c +++ b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_cfe_bootfs.c @@ -17,7 +17,7 @@ #define je16_to_cpu(x) ((x).v16) #define je32_to_cpu(x) ((x).v32) -#define NR_PARTS 1 +#define NR_PARTS 2 static int mtdsplit_cfe_bootfs_parse(struct mtd_info *mtd, const struct mtd_partition **pparts, @@ -58,12 +58,16 @@ static int mtdsplit_cfe_bootfs_parse(struct mtd_info *mtd, if (!parts) return -ENOMEM; + parts[0].name = "bootfs"; + parts[0].offset = 0; + parts[0].size = rootfs_offset; + if (type == MTDSPLIT_PART_TYPE_UBI) - parts[0].name = UBI_PART_NAME; + parts[1].name = UBI_PART_NAME; else - parts[0].name = ROOTFS_PART_NAME; - parts[0].offset = rootfs_offset; - parts[0].size = mtd->size - rootfs_offset; + parts[1].name = ROOTFS_PART_NAME; + parts[1].offset = rootfs_offset; + parts[1].size = mtd->size - rootfs_offset; *pparts = parts; From a3611432a6c3490fb2b6fdbc1ce664cf70900668 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Wed, 24 Mar 2021 22:44:14 +0100 Subject: [PATCH 21/31] firmware-utils: bcm4908kernel: name struct fields MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Less magic names / values. Signed-off-by: Rafał Miłecki --- tools/firmware-utils/src/bcm4908kernel.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tools/firmware-utils/src/bcm4908kernel.c b/tools/firmware-utils/src/bcm4908kernel.c index fc5b2812ef..eaf04a0a48 100644 --- a/tools/firmware-utils/src/bcm4908kernel.c +++ b/tools/firmware-utils/src/bcm4908kernel.c @@ -27,11 +27,11 @@ #endif struct bcm4908kernel_header { - uint32_t unk1; - uint32_t unk2; - uint32_t length; + uint32_t boot_load_addr; /* AKA la_address */ + uint32_t boot_addr; /* AKA la_entrypt */ + uint32_t data_len; uint8_t magic[4]; - uint32_t unused; + uint32_t uncomplen; /* Empty for LZMA, used for LZ4 */ }; static void usage() { @@ -103,14 +103,14 @@ int main(int argc, char **argv) { length += bytes; } - header.unk1 = cpu_to_le32(0x00080000); - header.unk2 = cpu_to_le32(0x00080000); - header.length = cpu_to_le32(length); + header.boot_load_addr = cpu_to_le32(0x00080000); + header.boot_addr = cpu_to_le32(0x00080000); + header.data_len = cpu_to_le32(length); header.magic[0] = 'B'; header.magic[1] = 'R'; header.magic[2] = 'C'; header.magic[3] = 'M'; - header.unused = 0; + header.uncomplen = 0; fseek(out, 0, SEEK_SET); From b6c366efa89dcaa96072b0a12a451f873aa90077 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Wed, 24 Mar 2021 22:53:23 +0000 Subject: [PATCH 22/31] image: fix append-image when building multiple profiles In case CONFIG_TARGET_MULTI_PROFILE is set, IMG_PREFIX cannot be expanded. Use DEVICE_IMG_PREFIX instead and make sure it's defined. Fixes: 8f89b1ab0f ("image: add 'append-image' build command") Signed-off-by: Daniel Golle --- include/image-commands.mk | 2 +- include/image.mk | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/image-commands.mk b/include/image-commands.mk index ec4f9624f5..2c56ed8d1d 100644 --- a/include/image-commands.mk +++ b/include/image-commands.mk @@ -28,7 +28,7 @@ define Build/append-kernel endef define Build/append-image - dd if=$(BIN_DIR)/$(IMG_PREFIX)$(if $(PROFILE_SANITIZED),-$(PROFILE_SANITIZED))-$(1) >> $@ + dd if=$(BIN_DIR)/$(DEVICE_IMG_PREFIX)-$(1) >> $@ endef compat_version=$(if $(DEVICE_COMPAT_VERSION),$(DEVICE_COMPAT_VERSION),1.0) diff --git a/include/image.mk b/include/image.mk index 8b7b2b9740..76c527a15e 100644 --- a/include/image.mk +++ b/include/image.mk @@ -419,7 +419,7 @@ DEFAULT_DEVICE_VARS := \ CMDLINE UBOOTENV_IN_UBI KERNEL_IN_UBI BLOCKSIZE PAGESIZE SUBPAGESIZE \ VID_HDR_OFFSET UBINIZE_OPTS UBINIZE_PARTS MKUBIFS_OPTS DEVICE_DTS \ DEVICE_DTS_CONFIG DEVICE_DTS_DIR DEVICE_DTS_OVERLAY DEVICE_FDT_NUM \ - SOC BOARD_NAME UIMAGE_MAGIC UIMAGE_NAME \ + DEVICE_IMG_PREFIX SOC BOARD_NAME UIMAGE_MAGIC UIMAGE_NAME \ SUPPORTED_DEVICES IMAGE_METADATA KERNEL_ENTRY KERNEL_LOADADDR \ UBOOT_PATH IMAGE_SIZE \ DEVICE_COMPAT_VERSION DEVICE_COMPAT_MESSAGE \ From 1bf2b3fe90347641c87ca754913a4857a387478c Mon Sep 17 00:00:00 2001 From: Paul Spooren Date: Wed, 24 Mar 2021 11:01:46 -1000 Subject: [PATCH 23/31] build,json: fixup missing arch_packages Fix 7f4c2b1 "build,json: fix duplicates in default_packages" which removed duplicate default packages but also removed the package architecture from the profiles.json. If DUMP=1 is set, the `ARCH_PACKAGES` is no longer exported and therefore empty. Fix this by running make twice, once with DUMP=1 and once without. Signed-off-by: Paul Spooren --- scripts/json_overview_image_info.py | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/scripts/json_overview_image_info.py b/scripts/json_overview_image_info.py index 23d8dcb857..e0e1ff08d5 100755 --- a/scripts/json_overview_image_info.py +++ b/scripts/json_overview_image_info.py @@ -33,14 +33,13 @@ for json_file in work_dir.glob("*.json"): ) if output: - default_packages, output["arch_packages"] = run( + output["default_packages"] = run( [ "make", "--no-print-directory", "-C", "target/linux/{}".format(output["target"].split("/")[0]), "val.DEFAULT_PACKAGES", - "val.ARCH_PACKAGES", "DUMP=1", ], stdout=PIPE, @@ -48,9 +47,21 @@ if output: check=True, env=environ.copy().update({"TOPDIR": Path().cwd()}), universal_newlines=True, - ).stdout.splitlines() + ).stdout.split() + + output["arch_packages"] = run( + [ + "make", + "--no-print-directory", + "val.ARCH_PACKAGES", + ], + stdout=PIPE, + stderr=PIPE, + check=True, + env=environ.copy().update({"TOPDIR": Path().cwd()}), + universal_newlines=True, + ).stdout.strip() - output["default_packages"] = default_packages.split() output_path.write_text(json.dumps(output, sort_keys=True, separators=(",", ":"))) else: print("JSON info file script could not find any JSON files for target") From af22991e03cae55f96b06996df2ff16752cec5d5 Mon Sep 17 00:00:00 2001 From: Philip Prindeville Date: Fri, 19 Mar 2021 15:09:45 -0600 Subject: [PATCH 24/31] build: make sure asm gets built with -DPIC Fixes issue openwrt/packages#14921, whereby inline ASM wasn't getting built as PIC; look at gmp-6.2.1/mpn/x86/pentium/popcount.asm for example: ifdef(`PIC',` ... for a routine that exists in both PIC and non-PIC versions. Make sure that wherever $(FPIC) gets passed as a variable expansion that it gets quoted where necessary (such as setting environment variables in shell commands). Signed-off-by: Philip Prindeville --- rules.mk | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rules.mk b/rules.mk index 8f41ff5861..f31d9bb113 100644 --- a/rules.mk +++ b/rules.mk @@ -75,12 +75,12 @@ IS_PACKAGE_BUILD := $(if $(filter package/%,$(BUILD_SUBDIR)),1) OPTIMIZE_FOR_CPU=$(subst i386,i486,$(ARCH)) ifneq (,$(findstring $(ARCH) , aarch64 aarch64_be powerpc )) - FPIC:=-fPIC + FPIC:=-DPIC -fPIC else - FPIC:=-fpic + FPIC:=-DPIC -fpic endif -HOST_FPIC:=-fPIC +HOST_FPIC:=-DPIC -fPIC ARCH_SUFFIX:=$(call qstrip,$(CONFIG_CPU_TYPE)) GCC_ARCH:= From 8c8496435a9d6a89eeb1b91b9d600362a0b24b16 Mon Sep 17 00:00:00 2001 From: Kevin Darbyshire-Bryant Date: Mon, 4 Jan 2021 20:55:38 +0000 Subject: [PATCH 25/31] build: add GNU install to prerequisites The recent removal of usbutils from core and replacement by hwdata in packages has exposed hwdata's requirement for certain GNU options on 'install' (-T) Other packages (sqm-scripts) have openwrt specific makefile sections to avoid GNU options but I suspect this is going to get harder in the future. Add GNU install as a prerequisite and link into $STAGING_DIR/host/etc/bin as per similar GNU utils This resolves an issue building under MacOS which would otherwise use a non-GNU options aware version of 'install' Signed-off-by: Kevin Darbyshire-Bryant --- include/prereq-build.mk | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/prereq-build.mk b/include/prereq-build.mk index b2526a1ec1..0375ef6861 100644 --- a/include/prereq-build.mk +++ b/include/prereq-build.mk @@ -136,6 +136,10 @@ $(eval $(call SetupHostCommand,bzip2,Please install 'bzip2', \ $(eval $(call SetupHostCommand,wget,Please install GNU 'wget', \ wget --version | grep GNU)) +$(eval $(call SetupHostCommand,install,Please install GNU 'install', \ + install --version | grep GNU, \ + ginstall --version | grep GNU)) + $(eval $(call SetupHostCommand,perl,Please install Perl 5.x, \ perl --version | grep "perl.*v5")) From b36068d35d9edbd8ed6aaeed6f4c863bfe4cfbee Mon Sep 17 00:00:00 2001 From: Paul Spooren Date: Wed, 24 Mar 2021 18:54:36 -1000 Subject: [PATCH 26/31] build,json: fixup fixup of arch_packages The commit "1bf2b3fe90 build,json: fixup missing arch_packages" fixes the missing package architecture locally but runs $(TOPDIR)/Makefile rather than a target specific one. While this works on local builds just fine, it causes the buildbots to add garbage to the `arch_packages` variable: cd \"/builder/shared-workdir/build\"; git log --format=%h -1 toolchain > /builder/shared-workdir/build/tmp/.ver_check\ncmp -s /builder/shared-workdir/build/tmp/.ver_check /builder/shared-workdir/build/staging_dir/toolchain-x86_64_gcc-8.4.0_musl/stamp/.ver_check || { \\\n\trm -rf /builder/shared-workdir/build/build_dir/target-x86_64_musl /builder/shared-workdir/build/staging_dir/target-x86_64_musl /builder/shared-workdir/build/staging_dir/toolchain-x86_64_gcc-8.4.0_musl /builder/shared-workdir/build/build_dir/toolchain-x86_64_gcc-8.4.0_musl; \\\n\tmkdir -p /builder/shared-workdir/build/staging_dir/toolchain-x86_64_gcc-8.4.0_musl/stamp; \\\n\tmv /builder/shared-workdir/build/tmp/.ver_check /builder/shared-workdir/build/staging_dir/toolchain-x86_64_gcc-8.4.0_musl/stamp/.ver_check; \\\n}\nx86_64 Only the last line contains the desired string. Future investigation should check why the build system prints this to stdout rather than stderr. Signed-off-by: Paul Spooren --- scripts/json_overview_image_info.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/json_overview_image_info.py b/scripts/json_overview_image_info.py index e0e1ff08d5..cd814a19c0 100755 --- a/scripts/json_overview_image_info.py +++ b/scripts/json_overview_image_info.py @@ -53,6 +53,8 @@ if output: [ "make", "--no-print-directory", + "-C", + "target/linux/{}".format(output["target"].split("/")[0]), "val.ARCH_PACKAGES", ], stdout=PIPE, From 7880a648484eb9d9cda87078660567f2e7e565e2 Mon Sep 17 00:00:00 2001 From: Paul Spooren Date: Thu, 25 Mar 2021 10:25:54 -1000 Subject: [PATCH 27/31] build,json: 3rd fixup of default_packages This became a bit of a tragedy, caused by a corner cases which wasn't put into account during testing. DEFAULT_PACKAGES are defined in target/linux//Makefile but also in target/linux///target.mk. The latter was no longer imported when using DUMP=1, however not using DUMP=1 while running the Makefile in target/linux// caused duplicate packages in the list. As a solution, which should have been used from day 0, `make` runs in target/linux/ without DUMP=1, resulting in no duplicate packages and all inclusions from include/target.mk, linux/target//{Makefile, /target.mk} While at it, sort the list of default packages. Signed-off-by: Paul Spooren --- scripts/json_overview_image_info.py | 23 +++++------------------ 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/scripts/json_overview_image_info.py b/scripts/json_overview_image_info.py index cd814a19c0..8dbd24af2d 100755 --- a/scripts/json_overview_image_info.py +++ b/scripts/json_overview_image_info.py @@ -33,28 +33,13 @@ for json_file in work_dir.glob("*.json"): ) if output: - output["default_packages"] = run( + default_packages, output["arch_packages"] = run( [ "make", "--no-print-directory", "-C", - "target/linux/{}".format(output["target"].split("/")[0]), + "target/linux/", "val.DEFAULT_PACKAGES", - "DUMP=1", - ], - stdout=PIPE, - stderr=PIPE, - check=True, - env=environ.copy().update({"TOPDIR": Path().cwd()}), - universal_newlines=True, - ).stdout.split() - - output["arch_packages"] = run( - [ - "make", - "--no-print-directory", - "-C", - "target/linux/{}".format(output["target"].split("/")[0]), "val.ARCH_PACKAGES", ], stdout=PIPE, @@ -62,7 +47,9 @@ if output: check=True, env=environ.copy().update({"TOPDIR": Path().cwd()}), universal_newlines=True, - ).stdout.strip() + ).stdout.splitlines() + + output["default_packages"] = sorted(default_packages.split()) output_path.write_text(json.dumps(output, sort_keys=True, separators=(",", ":"))) else: From 27344b378453030f5f35ef4ff5c6ec55c3ff29cb Mon Sep 17 00:00:00 2001 From: Rui Salvaterra Date: Thu, 25 Mar 2021 09:32:18 +0000 Subject: [PATCH 28/31] kernel: bump 5.10 to 5.10.26 Automatically refreshed: ath79/patches-5.10/471-mtd-cfi_cmdset_0002-AMD-chip-0x2201-write-words.patch bcm63xx/patches-5.10/143-gpio-fix-device-tree-gpio-hogs-on-dual-role-gpio-pin.patch generic/hack-5.10/204-module_strip.patch Run-tested: ath79 (TL-WDR3600) x86_64 (APU2 - ldir) Tested-by: Kevin Darbyshire-Bryant Signed-off-by: Rui Salvaterra --- include/kernel-version.mk | 4 ++-- ...mtd-cfi_cmdset_0002-AMD-chip-0x2201-write-words.patch | 9 +-------- ...fix-device-tree-gpio-hogs-on-dual-role-gpio-pin.patch | 4 ++-- target/linux/generic/hack-5.10/204-module_strip.patch | 4 ++-- 4 files changed, 7 insertions(+), 14 deletions(-) diff --git a/include/kernel-version.mk b/include/kernel-version.mk index 2dd18d7c0b..e7bc91c06e 100644 --- a/include/kernel-version.mk +++ b/include/kernel-version.mk @@ -7,10 +7,10 @@ ifdef CONFIG_TESTING_KERNEL endif LINUX_VERSION-5.4 = .106 -LINUX_VERSION-5.10 = .25 +LINUX_VERSION-5.10 = .26 LINUX_KERNEL_HASH-5.4.106 = cc873b2c39c1823d4bc4f6cde527943c8cfd28ae94cb517804b0f9679359c8db -LINUX_KERNEL_HASH-5.10.25 = 930ae76b9a3b64b98802849aca332d17a706f20595de21e1ae729b55ee461add +LINUX_KERNEL_HASH-5.10.26 = fc532833f1ac167f363f1b9de85db39d2d635ab516f66dc381bdd70804601482 remove_uri_prefix=$(subst git://,,$(subst http://,,$(subst https://,,$(1)))) sanitize_uri=$(call qstrip,$(subst @,_,$(subst :,_,$(subst .,_,$(subst -,_,$(subst /,_,$(1))))))) diff --git a/target/linux/ath79/patches-5.10/471-mtd-cfi_cmdset_0002-AMD-chip-0x2201-write-words.patch b/target/linux/ath79/patches-5.10/471-mtd-cfi_cmdset_0002-AMD-chip-0x2201-write-words.patch index 3c80872ef4..35ea92a7bc 100644 --- a/target/linux/ath79/patches-5.10/471-mtd-cfi_cmdset_0002-AMD-chip-0x2201-write-words.patch +++ b/target/linux/ath79/patches-5.10/471-mtd-cfi_cmdset_0002-AMD-chip-0x2201-write-words.patch @@ -36,11 +36,9 @@ Signed-off-by: Mauri Sandberg drivers/mtd/chips/cfi_cmdset_0002.c | 4 ++++ 1 file changed, 4 insertions(+) -diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c -index a1f3e1031c3d..28b6f3583f8a 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c -@@ -272,6 +272,10 @@ static void fixup_use_write_buffers(struct mtd_info *mtd) +@@ -272,6 +272,10 @@ static void fixup_use_write_buffers(stru { struct map_info *map = mtd->priv; struct cfi_private *cfi = map->fldrv_priv; @@ -51,8 +49,3 @@ index a1f3e1031c3d..28b6f3583f8a 100644 if (cfi->cfiq->BufWriteTimeoutTyp) { pr_debug("Using buffer write method\n"); mtd->_write = cfi_amdstd_write_buffers; - -base-commit: 5de15b610f785f0e188fefb707f0b19de156968a --- -2.25.1 - diff --git a/target/linux/bcm63xx/patches-5.10/143-gpio-fix-device-tree-gpio-hogs-on-dual-role-gpio-pin.patch b/target/linux/bcm63xx/patches-5.10/143-gpio-fix-device-tree-gpio-hogs-on-dual-role-gpio-pin.patch index 2b58b4841a..b35242efae 100644 --- a/target/linux/bcm63xx/patches-5.10/143-gpio-fix-device-tree-gpio-hogs-on-dual-role-gpio-pin.patch +++ b/target/linux/bcm63xx/patches-5.10/143-gpio-fix-device-tree-gpio-hogs-on-dual-role-gpio-pin.patch @@ -116,7 +116,7 @@ Signed-off-by: Jonas Gorski } --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c -@@ -1890,7 +1890,8 @@ int gpiochip_add_pingroup_range(struct g +@@ -1897,7 +1897,8 @@ int gpiochip_add_pingroup_range(struct g list_add_tail(&pin_range->node, &gdev->pin_ranges); @@ -126,7 +126,7 @@ Signed-off-by: Jonas Gorski } EXPORT_SYMBOL_GPL(gpiochip_add_pingroup_range); -@@ -1947,7 +1948,7 @@ int gpiochip_add_pin_range(struct gpio_c +@@ -1954,7 +1955,7 @@ int gpiochip_add_pin_range(struct gpio_c list_add_tail(&pin_range->node, &gdev->pin_ranges); diff --git a/target/linux/generic/hack-5.10/204-module_strip.patch b/target/linux/generic/hack-5.10/204-module_strip.patch index 2a162600fc..06159b0120 100644 --- a/target/linux/generic/hack-5.10/204-module_strip.patch +++ b/target/linux/generic/hack-5.10/204-module_strip.patch @@ -104,7 +104,7 @@ Signed-off-by: Felix Fietkau config MODULES_TREE_LOOKUP --- a/kernel/module.c +++ b/kernel/module.c -@@ -3161,9 +3161,11 @@ static int setup_load_info(struct load_i +@@ -3243,9 +3243,11 @@ static int setup_load_info(struct load_i static int check_modinfo(struct module *mod, struct load_info *info, int flags) { @@ -117,7 +117,7 @@ Signed-off-by: Felix Fietkau if (flags & MODULE_INIT_IGNORE_VERMAGIC) modmagic = NULL; -@@ -3184,6 +3186,7 @@ static int check_modinfo(struct module * +@@ -3266,6 +3268,7 @@ static int check_modinfo(struct module * mod->name); add_taint_module(mod, TAINT_OOT_MODULE, LOCKDEP_STILL_OK); } From 9390e20dba60753e3bedcd21e69c9cea41f56b17 Mon Sep 17 00:00:00 2001 From: Tony Ambardar Date: Wed, 24 Feb 2021 08:52:22 -0800 Subject: [PATCH 29/31] elfutils: enable building with MIPS16 Building with MIPS16 was disabled in 2013 due to an issue with GCC TLS: https://dev.archive.openwrt.org/ticket/13572. But after the problematic GCC version was retired, this change wasn't revisited. Re-enable MIPS16 builds to reduce average elfutils library sizes ~10%. This was compile-tested on malta/mips32be and malta/mips32le, and linked with iproute2 for run-testing. Package sizes follow: Library MIPS16:=0 MIPS16:=1 ------- --------- --------- libelf1 43217 37492 libasm1 12481 11658 libdw1 229723 205793 Signed-off-by: Tony Ambardar --- package/libs/elfutils/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package/libs/elfutils/Makefile b/package/libs/elfutils/Makefile index dd0b8ecdde..3e36dc27b8 100644 --- a/package/libs/elfutils/Makefile +++ b/package/libs/elfutils/Makefile @@ -8,7 +8,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=elfutils PKG_VERSION:=0.180 -PKG_RELEASE:=1 +PKG_RELEASE:=2 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2 PKG_SOURCE_URL:=https://sourceware.org/$(PKG_NAME)/ftp/$(PKG_VERSION) @@ -21,7 +21,7 @@ PKG_CPE_ID:=cpe:/a:elfutils_project:elfutils PKG_FIXUP:=autoreconf PKG_INSTALL:=1 -PKG_USE_MIPS16:=0 +PKG_USE_MIPS16:=1 PKG_BUILD_DEPENDS:=!USE_GLIBC:argp-standalone include $(INCLUDE_DIR)/package.mk From e27ef2da0d513494c3e9926ce8d44b63e4236a32 Mon Sep 17 00:00:00 2001 From: Kevin Darbyshire-Bryant Date: Fri, 26 Mar 2021 08:58:07 +0000 Subject: [PATCH 30/31] openssl: refresh patches Tidy up some patch fuzz. Signed-off-by: Kevin Darbyshire-Bryant --- .../patches/100-Configure-afalg-support.patch | 4 +- .../openssl/patches/110-openwrt_targets.patch | 3 - .../120-strip-cflags-from-binary.patch | 4 +- .../patches/130-dont-build-tests-fuzz.patch | 4 +- .../patches/140-allow-prefer-chacha20.patch | 8 +- ...o-save-ioctl-if-EVP_MD_.FLAG_ONESHOT.patch | 6 +- ..._devcrypto-add-configuration-options.patch | 21 +- ...ypto-add-command-to-dump-driver-info.patch | 16 +- ...o-make-the-dev-crypto-engine-dynamic.patch | 2604 ++++++++++++++++- ...default-to-not-use-digests-in-engine.patch | 4 +- ...to-ignore-error-when-closing-session.patch | 4 +- 11 files changed, 2498 insertions(+), 180 deletions(-) diff --git a/package/libs/openssl/patches/100-Configure-afalg-support.patch b/package/libs/openssl/patches/100-Configure-afalg-support.patch index 98944103b5..f62c35879e 100644 --- a/package/libs/openssl/patches/100-Configure-afalg-support.patch +++ b/package/libs/openssl/patches/100-Configure-afalg-support.patch @@ -8,11 +8,9 @@ version to disable building the AFALG engine on openwrt targets. Signed-off-by: Eneas U de Queiroz -diff --git a/Configure b/Configure -index 5a699836f3..74d057c219 100755 --- a/Configure +++ b/Configure -@@ -1545,7 +1545,9 @@ unless ($disabled{"crypto-mdebug-backtrace"}) +@@ -1545,7 +1545,9 @@ unless ($disabled{"crypto-mdebug-backtra unless ($disabled{afalgeng}) { $config{afalgeng}=""; diff --git a/package/libs/openssl/patches/110-openwrt_targets.patch b/package/libs/openssl/patches/110-openwrt_targets.patch index d0530b4661..b2786e8fee 100644 --- a/package/libs/openssl/patches/110-openwrt_targets.patch +++ b/package/libs/openssl/patches/110-openwrt_targets.patch @@ -7,9 +7,6 @@ Targets are named: linux-$(CONFIG_ARCH)-openwrt Signed-off-by: Eneas U de Queiroz -diff --git a/Configurations/25-openwrt.conf b/Configurations/25-openwrt.conf -new file mode 100644 -index 0000000000..86a86d31e4 --- /dev/null +++ b/Configurations/25-openwrt.conf @@ -0,0 +1,48 @@ diff --git a/package/libs/openssl/patches/120-strip-cflags-from-binary.patch b/package/libs/openssl/patches/120-strip-cflags-from-binary.patch index 7faec9ab88..4a7dce366b 100644 --- a/package/libs/openssl/patches/120-strip-cflags-from-binary.patch +++ b/package/libs/openssl/patches/120-strip-cflags-from-binary.patch @@ -8,11 +8,9 @@ OpenSSL_version(OPENSSL_CFLAGS), or running openssl version -a Signed-off-by: Eneas U de Queiroz -diff --git a/crypto/build.info b/crypto/build.info -index 2c619c62e8..893128345a 100644 --- a/crypto/build.info +++ b/crypto/build.info -@@ -10,7 +10,7 @@ EXTRA= ../ms/uplink-x86.pl ../ms/uplink.c ../ms/applink.c \ +@@ -10,7 +10,7 @@ EXTRA= ../ms/uplink-x86.pl ../ms/uplink ppccpuid.pl pariscid.pl alphacpuid.pl arm64cpuid.pl armv4cpuid.pl DEPEND[cversion.o]=buildinf.h diff --git a/package/libs/openssl/patches/130-dont-build-tests-fuzz.patch b/package/libs/openssl/patches/130-dont-build-tests-fuzz.patch index 7f33cb9dae..1117f7152f 100644 --- a/package/libs/openssl/patches/130-dont-build-tests-fuzz.patch +++ b/package/libs/openssl/patches/130-dont-build-tests-fuzz.patch @@ -7,11 +7,9 @@ This shortens build time. Signed-off-by: Eneas U de Queiroz -diff --git a/Configure b/Configure -index 74d057c219..5813e9f8fe 100755 --- a/Configure +++ b/Configure -@@ -318,7 +318,7 @@ my $auto_threads=1; # enable threads automatically? true by default +@@ -318,7 +318,7 @@ my $auto_threads=1; # enable threads my $default_ranlib; # Top level directories to build diff --git a/package/libs/openssl/patches/140-allow-prefer-chacha20.patch b/package/libs/openssl/patches/140-allow-prefer-chacha20.patch index b293db28f7..71c7c72881 100644 --- a/package/libs/openssl/patches/140-allow-prefer-chacha20.patch +++ b/package/libs/openssl/patches/140-allow-prefer-chacha20.patch @@ -14,8 +14,6 @@ when the client has it on top of its ciphersuite preference. Signed-off-by: Eneas U de Queiroz -diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h -index 6724ccf2d2..96d959427e 100644 --- a/include/openssl/ssl.h +++ b/include/openssl/ssl.h @@ -173,9 +173,15 @@ extern "C" { @@ -37,11 +35,9 @@ index 6724ccf2d2..96d959427e 100644 # else # define TLS_DEFAULT_CIPHERSUITES "TLS_AES_256_GCM_SHA384:" \ "TLS_AES_128_GCM_SHA256" -diff --git a/ssl/ssl_ciph.c b/ssl/ssl_ciph.c -index 27a1b2ec68..7039811323 100644 --- a/ssl/ssl_ciph.c +++ b/ssl/ssl_ciph.c -@@ -1467,11 +1467,29 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method, +@@ -1467,11 +1467,29 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_ ssl_cipher_apply_rule(0, SSL_kECDHE, 0, 0, 0, 0, 0, CIPHER_DEL, -1, &head, &tail); @@ -71,7 +67,7 @@ index 27a1b2ec68..7039811323 100644 /* * ...and generally, our preferred cipher is AES. -@@ -1527,7 +1545,7 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method, +@@ -1527,7 +1545,7 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_ * Within each group, ciphers remain sorted by strength and previous * preference, i.e., * 1) ECDHE > DHE diff --git a/package/libs/openssl/patches/400-eng_devcrypto-save-ioctl-if-EVP_MD_.FLAG_ONESHOT.patch b/package/libs/openssl/patches/400-eng_devcrypto-save-ioctl-if-EVP_MD_.FLAG_ONESHOT.patch index 84c68b16a2..57962ec9c7 100644 --- a/package/libs/openssl/patches/400-eng_devcrypto-save-ioctl-if-EVP_MD_.FLAG_ONESHOT.patch +++ b/package/libs/openssl/patches/400-eng_devcrypto-save-ioctl-if-EVP_MD_.FLAG_ONESHOT.patch @@ -14,8 +14,6 @@ Reviewed-by: Matthias St. Pierre Reviewed-by: Richard Levitte (Merged from https://github.com/openssl/openssl/pull/7585) -diff --git a/crypto/engine/eng_devcrypto.c b/crypto/engine/eng_devcrypto.c -index a727c6f646..a2c9a966f7 100644 --- a/crypto/engine/eng_devcrypto.c +++ b/crypto/engine/eng_devcrypto.c @@ -461,6 +461,7 @@ struct digest_ctx { @@ -26,7 +24,7 @@ index a727c6f646..a2c9a966f7 100644 }; static const struct digest_data_st { -@@ -564,12 +565,15 @@ static int digest_update(EVP_MD_CTX *ctx, const void *data, size_t count) +@@ -564,12 +565,15 @@ static int digest_update(EVP_MD_CTX *ctx if (digest_ctx == NULL) return 0; @@ -46,7 +44,7 @@ index a727c6f646..a2c9a966f7 100644 } static int digest_final(EVP_MD_CTX *ctx, unsigned char *md) -@@ -579,7 +583,10 @@ static int digest_final(EVP_MD_CTX *ctx, unsigned char *md) +@@ -579,7 +583,10 @@ static int digest_final(EVP_MD_CTX *ctx, if (md == NULL || digest_ctx == NULL) return 0; diff --git a/package/libs/openssl/patches/410-eng_devcrypto-add-configuration-options.patch b/package/libs/openssl/patches/410-eng_devcrypto-add-configuration-options.patch index 8745364cf2..12fe7b4199 100644 --- a/package/libs/openssl/patches/410-eng_devcrypto-add-configuration-options.patch +++ b/package/libs/openssl/patches/410-eng_devcrypto-add-configuration-options.patch @@ -13,8 +13,6 @@ Reviewed-by: Matthias St. Pierre Reviewed-by: Richard Levitte (Merged from https://github.com/openssl/openssl/pull/7585) -diff --git a/crypto/engine/eng_devcrypto.c b/crypto/engine/eng_devcrypto.c -index a2c9a966f7..5ec38ca8f3 100644 --- a/crypto/engine/eng_devcrypto.c +++ b/crypto/engine/eng_devcrypto.c @@ -16,6 +16,7 @@ @@ -80,7 +78,7 @@ index a2c9a966f7..5ec38ca8f3 100644 /* * Code further down must make sure that only NIDs in the table above -@@ -333,19 +367,40 @@ static int cipher_cleanup(EVP_CIPHER_CTX *ctx) +@@ -333,19 +367,40 @@ static int cipher_cleanup(EVP_CIPHER_CTX } /* @@ -186,7 +184,7 @@ index a2c9a966f7..5ec38ca8f3 100644 static const EVP_CIPHER *get_cipher_method(int nid) { size_t i = get_cipher_data_index(nid); -@@ -438,6 +520,36 @@ static int devcrypto_ciphers(ENGINE *e, const EVP_CIPHER **cipher, +@@ -438,6 +520,36 @@ static int devcrypto_ciphers(ENGINE *e, return *cipher != NULL; } @@ -247,7 +245,7 @@ index a2c9a966f7..5ec38ca8f3 100644 /* * Code further down must make sure that only NIDs in the table above -@@ -516,8 +637,8 @@ static const struct digest_data_st *get_digest_data(int nid) +@@ -516,8 +637,8 @@ static const struct digest_data_st *get_ } /* @@ -258,7 +256,7 @@ index a2c9a966f7..5ec38ca8f3 100644 */ static int digest_init(EVP_MD_CTX *ctx) -@@ -630,52 +751,94 @@ static int digest_cleanup(EVP_MD_CTX *ctx) +@@ -630,52 +751,94 @@ static int digest_cleanup(EVP_MD_CTX *ct return clean_devcrypto_session(&digest_ctx->sess); } @@ -403,7 +401,7 @@ index a2c9a966f7..5ec38ca8f3 100644 } } -@@ -739,8 +909,154 @@ static int devcrypto_digests(ENGINE *e, const EVP_MD **digest, +@@ -739,7 +909,153 @@ static int devcrypto_digests(ENGINE *e, return *digest != NULL; } @@ -479,8 +477,8 @@ index a2c9a966f7..5ec38ca8f3 100644 + "DIGESTS", + "either ALL, NONE, or a comma-separated list of digests to enable [default=ALL]", + ENGINE_CMD_FLAG_STRING}, - #endif - ++#endif ++ + {0, NULL, NULL, 0} +}; + @@ -504,7 +502,7 @@ index a2c9a966f7..5ec38ca8f3 100644 + use_softdrivers = i; +#ifdef IMPLEMENT_DIGEST + rebuild_known_digest_nids(e); -+#endif + #endif + rebuild_known_cipher_nids(e); + return 1; +#endif /* CIOCGSESSINFO */ @@ -554,10 +552,9 @@ index a2c9a966f7..5ec38ca8f3 100644 + } + return 0; +} -+ + /****************************************************************************** * - * LOAD / UNLOAD @@ -793,6 +1109,8 @@ void engine_load_devcrypto_int() if (!ENGINE_set_id(e, "devcrypto") diff --git a/package/libs/openssl/patches/420-eng_devcrypto-add-command-to-dump-driver-info.patch b/package/libs/openssl/patches/420-eng_devcrypto-add-command-to-dump-driver-info.patch index ad83a51a10..b7e1f6a411 100644 --- a/package/libs/openssl/patches/420-eng_devcrypto-add-command-to-dump-driver-info.patch +++ b/package/libs/openssl/patches/420-eng_devcrypto-add-command-to-dump-driver-info.patch @@ -11,11 +11,9 @@ Reviewed-by: Matthias St. Pierre Reviewed-by: Richard Levitte (Merged from https://github.com/openssl/openssl/pull/7585) -diff --git a/crypto/engine/eng_devcrypto.c b/crypto/engine/eng_devcrypto.c -index 5ec38ca8f3..64dc6b891d 100644 --- a/crypto/engine/eng_devcrypto.c +++ b/crypto/engine/eng_devcrypto.c -@@ -50,16 +50,20 @@ static int use_softdrivers = DEVCRYPTO_DEFAULT_USE_SOFDTRIVERS; +@@ -50,16 +50,20 @@ static int use_softdrivers = DEVCRYPTO_D */ struct driver_info_st { enum devcrypto_status_t { @@ -82,7 +80,7 @@ index 5ec38ca8f3..64dc6b891d 100644 #endif /* CIOCGSESSINFO */ } ioctl(cfd, CIOCFSESSION, &sess.ses); -@@ -505,8 +514,11 @@ static void destroy_all_cipher_methods(void) +@@ -505,8 +514,11 @@ static void destroy_all_cipher_methods(v { size_t i; @@ -95,7 +93,7 @@ index 5ec38ca8f3..64dc6b891d 100644 } static int devcrypto_ciphers(ENGINE *e, const EVP_CIPHER **cipher, -@@ -550,6 +562,40 @@ static int cryptodev_select_cipher_cb(const char *str, int len, void *usr) +@@ -550,6 +562,40 @@ static int cryptodev_select_cipher_cb(co return 1; } @@ -190,7 +188,7 @@ index 5ec38ca8f3..64dc6b891d 100644 EVP_MD_meth_free(known_digest_methods[i]); known_digest_methods[i] = NULL; goto finish; -@@ -894,8 +945,11 @@ static void destroy_all_digest_methods(void) +@@ -894,8 +945,11 @@ static void destroy_all_digest_methods(v { size_t i; @@ -203,7 +201,7 @@ index 5ec38ca8f3..64dc6b891d 100644 } static int devcrypto_digests(ENGINE *e, const EVP_MD **digest, -@@ -939,6 +993,43 @@ static int cryptodev_select_digest_cb(const char *str, int len, void *usr) +@@ -939,6 +993,43 @@ static int cryptodev_select_digest_cb(co return 1; } @@ -247,7 +245,7 @@ index 5ec38ca8f3..64dc6b891d 100644 #endif /****************************************************************************** -@@ -983,6 +1074,11 @@ static const ENGINE_CMD_DEFN devcrypto_cmds[] = { +@@ -983,6 +1074,11 @@ static const ENGINE_CMD_DEFN devcrypto_c ENGINE_CMD_FLAG_STRING}, #endif @@ -259,7 +257,7 @@ index 5ec38ca8f3..64dc6b891d 100644 {0, NULL, NULL, 0} }; -@@ -1051,6 +1147,13 @@ static int devcrypto_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void)) +@@ -1051,6 +1147,13 @@ static int devcrypto_ctrl(ENGINE *e, int return 1; #endif /* IMPLEMENT_DIGEST */ diff --git a/package/libs/openssl/patches/430-e_devcrypto-make-the-dev-crypto-engine-dynamic.patch b/package/libs/openssl/patches/430-e_devcrypto-make-the-dev-crypto-engine-dynamic.patch index 71dc5bf99b..4218fbe76c 100644 --- a/package/libs/openssl/patches/430-e_devcrypto-make-the-dev-crypto-engine-dynamic.patch +++ b/package/libs/openssl/patches/430-e_devcrypto-make-the-dev-crypto-engine-dynamic.patch @@ -8,8 +8,6 @@ engines/e_devcrypto.c. Signed-off-by: Eneas U de Queiroz -diff --git a/crypto/engine/build.info b/crypto/engine/build.info -index e00802a3fd..47fe948966 100644 --- a/crypto/engine/build.info +++ b/crypto/engine/build.info @@ -6,6 +6,3 @@ SOURCE[../../libcrypto]=\ @@ -19,11 +17,9 @@ index e00802a3fd..47fe948966 100644 -IF[{- !$disabled{devcryptoeng} -}] - SOURCE[../../libcrypto]=eng_devcrypto.c -ENDIF -diff --git a/crypto/init.c b/crypto/init.c -index 1b0d523bea..ee3e2eb075 100644 --- a/crypto/init.c +++ b/crypto/init.c -@@ -329,18 +329,6 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_engine_openssl) +@@ -329,18 +329,6 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_engine_ engine_load_openssl_int(); return 1; } @@ -42,7 +38,7 @@ index 1b0d523bea..ee3e2eb075 100644 # ifndef OPENSSL_NO_RDRAND static CRYPTO_ONCE engine_rdrand = CRYPTO_ONCE_STATIC_INIT; -@@ -365,6 +353,18 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_engine_dynamic) +@@ -365,6 +353,18 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_engine_ return 1; } # ifndef OPENSSL_NO_STATIC_ENGINE @@ -61,7 +57,7 @@ index 1b0d523bea..ee3e2eb075 100644 # if !defined(OPENSSL_NO_HW) && !defined(OPENSSL_NO_HW_PADLOCK) static CRYPTO_ONCE engine_padlock = CRYPTO_ONCE_STATIC_INIT; DEFINE_RUN_ONCE_STATIC(ossl_init_engine_padlock) -@@ -713,11 +713,6 @@ int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings) +@@ -713,11 +713,6 @@ int OPENSSL_init_crypto(uint64_t opts, c if ((opts & OPENSSL_INIT_ENGINE_OPENSSL) && !RUN_ONCE(&engine_openssl, ossl_init_engine_openssl)) return 0; @@ -73,7 +69,7 @@ index 1b0d523bea..ee3e2eb075 100644 # ifndef OPENSSL_NO_RDRAND if ((opts & OPENSSL_INIT_ENGINE_RDRAND) && !RUN_ONCE(&engine_rdrand, ossl_init_engine_rdrand)) -@@ -727,6 +722,11 @@ int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings) +@@ -727,6 +722,11 @@ int OPENSSL_init_crypto(uint64_t opts, c && !RUN_ONCE(&engine_dynamic, ossl_init_engine_dynamic)) return 0; # ifndef OPENSSL_NO_STATIC_ENGINE @@ -85,8 +81,6 @@ index 1b0d523bea..ee3e2eb075 100644 # if !defined(OPENSSL_NO_HW) && !defined(OPENSSL_NO_HW_PADLOCK) if ((opts & OPENSSL_INIT_ENGINE_PADLOCK) && !RUN_ONCE(&engine_padlock, ossl_init_engine_padlock)) -diff --git a/engines/build.info b/engines/build.info -index 1db771971c..33a25d7004 100644 --- a/engines/build.info +++ b/engines/build.info @@ -11,6 +11,9 @@ IF[{- !$disabled{"engine"} -}] @@ -112,75 +106,1177 @@ index 1db771971c..33a25d7004 100644 ENGINES_NO_INST=ossltest dasync SOURCE[dasync]=e_dasync.c -diff --git a/crypto/engine/eng_devcrypto.c b/engines/e_devcrypto.c -similarity index 95% -rename from crypto/engine/eng_devcrypto.c -rename to engines/e_devcrypto.c -index 0d420e50aa..3fcd81de7a 100644 --- a/crypto/engine/eng_devcrypto.c -+++ b/engines/e_devcrypto.c -@@ -7,7 +7,7 @@ - * https://www.openssl.org/source/license.html - */ - ++++ /dev/null +@@ -1,1264 +0,0 @@ +-/* +- * Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved. +- * +- * Licensed under the OpenSSL license (the "License"). You may not use +- * this file except in compliance with the License. You can obtain a copy +- * in the file LICENSE in the source distribution or at +- * https://www.openssl.org/source/license.html +- */ +- -#include "e_os.h" -+#include "../e_os.h" - #include - #include - #include -@@ -31,18 +31,20 @@ - # define CHECK_BSD_STYLE_MACROS - #endif - -+#define engine_devcrypto_id "devcrypto" -+ - /* - * ONE global file descriptor for all sessions. This allows operations - * such as digest session data copying (see digest_copy()), but is also - * saner... why re-open /dev/crypto for every session? - */ +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include "crypto/engine.h" +- +-/* #define ENGINE_DEVCRYPTO_DEBUG */ +- +-#if CRYPTO_ALGORITHM_MIN < CRYPTO_ALGORITHM_MAX +-# define CHECK_BSD_STYLE_MACROS +-#endif +- +-/* +- * ONE global file descriptor for all sessions. This allows operations +- * such as digest session data copying (see digest_copy()), but is also +- * saner... why re-open /dev/crypto for every session? +- */ -static int cfd; -+static int cfd = -1; - #define DEVCRYPTO_REQUIRE_ACCELERATED 0 /* require confirmation of acceleration */ - #define DEVCRYPTO_USE_SOFTWARE 1 /* allow software drivers */ - #define DEVCRYPTO_REJECT_SOFTWARE 2 /* only disallow confirmed software drivers */ - +-#define DEVCRYPTO_REQUIRE_ACCELERATED 0 /* require confirmation of acceleration */ +-#define DEVCRYPTO_USE_SOFTWARE 1 /* allow software drivers */ +-#define DEVCRYPTO_REJECT_SOFTWARE 2 /* only disallow confirmed software drivers */ +- -#define DEVCRYPTO_DEFAULT_USE_SOFDTRIVERS DEVCRYPTO_REJECT_SOFTWARE -static int use_softdrivers = DEVCRYPTO_DEFAULT_USE_SOFDTRIVERS; -+#define DEVCRYPTO_DEFAULT_USE_SOFTDRIVERS DEVCRYPTO_REJECT_SOFTWARE -+static int use_softdrivers = DEVCRYPTO_DEFAULT_USE_SOFTDRIVERS; - - /* - * cipher/digest status & acceleration definitions -@@ -341,6 +343,7 @@ static int cipher_ctrl(EVP_CIPHER_CTX *ctx, int type, int p1, void* p2) - struct cipher_ctx *to_cipher_ctx; - - switch (type) { -+ - case EVP_CTRL_COPY: - if (cipher_ctx == NULL) - return 1; -@@ -702,7 +705,6 @@ static int digest_init(EVP_MD_CTX *ctx) - SYSerr(SYS_F_IOCTL, errno); - return 0; - } - - return 1; - } - -@@ -1058,7 +1060,7 @@ static const ENGINE_CMD_DEFN devcrypto_cmds[] = { - OPENSSL_MSTR(DEVCRYPTO_USE_SOFTWARE) "=allow all drivers, " - OPENSSL_MSTR(DEVCRYPTO_REJECT_SOFTWARE) - "=use if acceleration can't be determined) [default=" +-/* +- * cipher/digest status & acceleration definitions +- * Make sure the defaults are set to 0 +- */ +-struct driver_info_st { +- enum devcrypto_status_t { +- DEVCRYPTO_STATUS_FAILURE = -3, /* unusable for other reason */ +- DEVCRYPTO_STATUS_NO_CIOCCPHASH = -2, /* hash state copy not supported */ +- DEVCRYPTO_STATUS_NO_CIOCGSESSION = -1, /* session open failed */ +- DEVCRYPTO_STATUS_UNKNOWN = 0, /* not tested yet */ +- DEVCRYPTO_STATUS_USABLE = 1 /* algo can be used */ +- } status; +- +- enum devcrypto_accelerated_t { +- DEVCRYPTO_NOT_ACCELERATED = -1, /* software implemented */ +- DEVCRYPTO_ACCELERATION_UNKNOWN = 0, /* acceleration support unkown */ +- DEVCRYPTO_ACCELERATED = 1 /* hardware accelerated */ +- } accelerated; +- +- char *driver_name; +-}; +- +-static int clean_devcrypto_session(struct session_op *sess) { +- if (ioctl(cfd, CIOCFSESSION, &sess->ses) < 0) { +- SYSerr(SYS_F_IOCTL, errno); +- return 0; +- } +- memset(sess, 0, sizeof(struct session_op)); +- return 1; +-} +- +-/****************************************************************************** +- * +- * Ciphers +- * +- * Because they all do the same basic operation, we have only one set of +- * method functions for them all to share, and a mapping table between +- * NIDs and cryptodev IDs, with all the necessary size data. +- * +- *****/ +- +-struct cipher_ctx { +- struct session_op sess; +- int op; /* COP_ENCRYPT or COP_DECRYPT */ +- unsigned long mode; /* EVP_CIPH_*_MODE */ +- +- /* to handle ctr mode being a stream cipher */ +- unsigned char partial[EVP_MAX_BLOCK_LENGTH]; +- unsigned int blocksize, num; +-}; +- +-static const struct cipher_data_st { +- int nid; +- int blocksize; +- int keylen; +- int ivlen; +- int flags; +- int devcryptoid; +-} cipher_data[] = { +-#ifndef OPENSSL_NO_DES +- { NID_des_cbc, 8, 8, 8, EVP_CIPH_CBC_MODE, CRYPTO_DES_CBC }, +- { NID_des_ede3_cbc, 8, 24, 8, EVP_CIPH_CBC_MODE, CRYPTO_3DES_CBC }, +-#endif +-#ifndef OPENSSL_NO_BF +- { NID_bf_cbc, 8, 16, 8, EVP_CIPH_CBC_MODE, CRYPTO_BLF_CBC }, +-#endif +-#ifndef OPENSSL_NO_CAST +- { NID_cast5_cbc, 8, 16, 8, EVP_CIPH_CBC_MODE, CRYPTO_CAST_CBC }, +-#endif +- { NID_aes_128_cbc, 16, 128 / 8, 16, EVP_CIPH_CBC_MODE, CRYPTO_AES_CBC }, +- { NID_aes_192_cbc, 16, 192 / 8, 16, EVP_CIPH_CBC_MODE, CRYPTO_AES_CBC }, +- { NID_aes_256_cbc, 16, 256 / 8, 16, EVP_CIPH_CBC_MODE, CRYPTO_AES_CBC }, +-#ifndef OPENSSL_NO_RC4 +- { NID_rc4, 1, 16, 0, EVP_CIPH_STREAM_CIPHER, CRYPTO_ARC4 }, +-#endif +-#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_AES_CTR) +- { NID_aes_128_ctr, 16, 128 / 8, 16, EVP_CIPH_CTR_MODE, CRYPTO_AES_CTR }, +- { NID_aes_192_ctr, 16, 192 / 8, 16, EVP_CIPH_CTR_MODE, CRYPTO_AES_CTR }, +- { NID_aes_256_ctr, 16, 256 / 8, 16, EVP_CIPH_CTR_MODE, CRYPTO_AES_CTR }, +-#endif +-#if 0 /* Not yet supported */ +- { NID_aes_128_xts, 16, 128 / 8 * 2, 16, EVP_CIPH_XTS_MODE, CRYPTO_AES_XTS }, +- { NID_aes_256_xts, 16, 256 / 8 * 2, 16, EVP_CIPH_XTS_MODE, CRYPTO_AES_XTS }, +-#endif +-#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_AES_ECB) +- { NID_aes_128_ecb, 16, 128 / 8, 0, EVP_CIPH_ECB_MODE, CRYPTO_AES_ECB }, +- { NID_aes_192_ecb, 16, 192 / 8, 0, EVP_CIPH_ECB_MODE, CRYPTO_AES_ECB }, +- { NID_aes_256_ecb, 16, 256 / 8, 0, EVP_CIPH_ECB_MODE, CRYPTO_AES_ECB }, +-#endif +-#if 0 /* Not yet supported */ +- { NID_aes_128_gcm, 16, 128 / 8, 16, EVP_CIPH_GCM_MODE, CRYPTO_AES_GCM }, +- { NID_aes_192_gcm, 16, 192 / 8, 16, EVP_CIPH_GCM_MODE, CRYPTO_AES_GCM }, +- { NID_aes_256_gcm, 16, 256 / 8, 16, EVP_CIPH_GCM_MODE, CRYPTO_AES_GCM }, +-#endif +-#ifndef OPENSSL_NO_CAMELLIA +- { NID_camellia_128_cbc, 16, 128 / 8, 16, EVP_CIPH_CBC_MODE, +- CRYPTO_CAMELLIA_CBC }, +- { NID_camellia_192_cbc, 16, 192 / 8, 16, EVP_CIPH_CBC_MODE, +- CRYPTO_CAMELLIA_CBC }, +- { NID_camellia_256_cbc, 16, 256 / 8, 16, EVP_CIPH_CBC_MODE, +- CRYPTO_CAMELLIA_CBC }, +-#endif +-}; +- +-static size_t find_cipher_data_index(int nid) +-{ +- size_t i; +- +- for (i = 0; i < OSSL_NELEM(cipher_data); i++) +- if (nid == cipher_data[i].nid) +- return i; +- return (size_t)-1; +-} +- +-static size_t get_cipher_data_index(int nid) +-{ +- size_t i = find_cipher_data_index(nid); +- +- if (i != (size_t)-1) +- return i; +- +- /* +- * Code further down must make sure that only NIDs in the table above +- * are used. If any other NID reaches this function, there's a grave +- * coding error further down. +- */ +- assert("Code that never should be reached" == NULL); +- return -1; +-} +- +-static const struct cipher_data_st *get_cipher_data(int nid) +-{ +- return &cipher_data[get_cipher_data_index(nid)]; +-} +- +-/* +- * Following are the three necessary functions to map OpenSSL functionality +- * with cryptodev. +- */ +- +-static int cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, +- const unsigned char *iv, int enc) +-{ +- struct cipher_ctx *cipher_ctx = +- (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx); +- const struct cipher_data_st *cipher_d = +- get_cipher_data(EVP_CIPHER_CTX_nid(ctx)); +- +- /* cleanup a previous session */ +- if (cipher_ctx->sess.ses != 0 && +- clean_devcrypto_session(&cipher_ctx->sess) == 0) +- return 0; +- +- cipher_ctx->sess.cipher = cipher_d->devcryptoid; +- cipher_ctx->sess.keylen = cipher_d->keylen; +- cipher_ctx->sess.key = (void *)key; +- cipher_ctx->op = enc ? COP_ENCRYPT : COP_DECRYPT; +- cipher_ctx->mode = cipher_d->flags & EVP_CIPH_MODE; +- cipher_ctx->blocksize = cipher_d->blocksize; +- if (ioctl(cfd, CIOCGSESSION, &cipher_ctx->sess) < 0) { +- SYSerr(SYS_F_IOCTL, errno); +- return 0; +- } +- +- return 1; +-} +- +-static int cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +- const unsigned char *in, size_t inl) +-{ +- struct cipher_ctx *cipher_ctx = +- (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx); +- struct crypt_op cryp; +- unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx); +-#if !defined(COP_FLAG_WRITE_IV) +- unsigned char saved_iv[EVP_MAX_IV_LENGTH]; +- const unsigned char *ivptr; +- size_t nblocks, ivlen; +-#endif +- +- memset(&cryp, 0, sizeof(cryp)); +- cryp.ses = cipher_ctx->sess.ses; +- cryp.len = inl; +- cryp.src = (void *)in; +- cryp.dst = (void *)out; +- cryp.iv = (void *)iv; +- cryp.op = cipher_ctx->op; +-#if !defined(COP_FLAG_WRITE_IV) +- cryp.flags = 0; +- +- ivlen = EVP_CIPHER_CTX_iv_length(ctx); +- if (ivlen > 0) +- switch (cipher_ctx->mode) { +- case EVP_CIPH_CBC_MODE: +- assert(inl >= ivlen); +- if (!EVP_CIPHER_CTX_encrypting(ctx)) { +- ivptr = in + inl - ivlen; +- memcpy(saved_iv, ivptr, ivlen); +- } +- break; +- +- case EVP_CIPH_CTR_MODE: +- break; +- +- default: /* should not happen */ +- return 0; +- } +-#else +- cryp.flags = COP_FLAG_WRITE_IV; +-#endif +- +- if (ioctl(cfd, CIOCCRYPT, &cryp) < 0) { +- SYSerr(SYS_F_IOCTL, errno); +- return 0; +- } +- +-#if !defined(COP_FLAG_WRITE_IV) +- if (ivlen > 0) +- switch (cipher_ctx->mode) { +- case EVP_CIPH_CBC_MODE: +- assert(inl >= ivlen); +- if (EVP_CIPHER_CTX_encrypting(ctx)) +- ivptr = out + inl - ivlen; +- else +- ivptr = saved_iv; +- +- memcpy(iv, ivptr, ivlen); +- break; +- +- case EVP_CIPH_CTR_MODE: +- nblocks = (inl + cipher_ctx->blocksize - 1) +- / cipher_ctx->blocksize; +- do { +- ivlen--; +- nblocks += iv[ivlen]; +- iv[ivlen] = (uint8_t) nblocks; +- nblocks >>= 8; +- } while (ivlen); +- break; +- +- default: /* should not happen */ +- return 0; +- } +-#endif +- +- return 1; +-} +- +-static int ctr_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +- const unsigned char *in, size_t inl) +-{ +- struct cipher_ctx *cipher_ctx = +- (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx); +- size_t nblocks, len; +- +- /* initial partial block */ +- while (cipher_ctx->num && inl) { +- (*out++) = *(in++) ^ cipher_ctx->partial[cipher_ctx->num]; +- --inl; +- cipher_ctx->num = (cipher_ctx->num + 1) % cipher_ctx->blocksize; +- } +- +- /* full blocks */ +- if (inl > (unsigned int) cipher_ctx->blocksize) { +- nblocks = inl/cipher_ctx->blocksize; +- len = nblocks * cipher_ctx->blocksize; +- if (cipher_do_cipher(ctx, out, in, len) < 1) +- return 0; +- inl -= len; +- out += len; +- in += len; +- } +- +- /* final partial block */ +- if (inl) { +- memset(cipher_ctx->partial, 0, cipher_ctx->blocksize); +- if (cipher_do_cipher(ctx, cipher_ctx->partial, cipher_ctx->partial, +- cipher_ctx->blocksize) < 1) +- return 0; +- while (inl--) { +- out[cipher_ctx->num] = in[cipher_ctx->num] +- ^ cipher_ctx->partial[cipher_ctx->num]; +- cipher_ctx->num++; +- } +- } +- +- return 1; +-} +- +-static int cipher_ctrl(EVP_CIPHER_CTX *ctx, int type, int p1, void* p2) +-{ +- struct cipher_ctx *cipher_ctx = +- (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx); +- EVP_CIPHER_CTX *to_ctx = (EVP_CIPHER_CTX *)p2; +- struct cipher_ctx *to_cipher_ctx; +- +- switch (type) { +- case EVP_CTRL_COPY: +- if (cipher_ctx == NULL) +- return 1; +- /* when copying the context, a new session needs to be initialized */ +- to_cipher_ctx = +- (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(to_ctx); +- memset(&to_cipher_ctx->sess, 0, sizeof(to_cipher_ctx->sess)); +- return cipher_init(to_ctx, cipher_ctx->sess.key, EVP_CIPHER_CTX_iv(ctx), +- (cipher_ctx->op == COP_ENCRYPT)); +- +- case EVP_CTRL_INIT: +- memset(&cipher_ctx->sess, 0, sizeof(cipher_ctx->sess)); +- return 1; +- +- default: +- break; +- } +- +- return -1; +-} +- +-static int cipher_cleanup(EVP_CIPHER_CTX *ctx) +-{ +- struct cipher_ctx *cipher_ctx = +- (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx); +- +- return clean_devcrypto_session(&cipher_ctx->sess); +-} +- +-/* +- * Keep tables of known nids, associated methods, selected ciphers, and driver +- * info. +- * Note that known_cipher_nids[] isn't necessarily indexed the same way as +- * cipher_data[] above, which the other tables are. +- */ +-static int known_cipher_nids[OSSL_NELEM(cipher_data)]; +-static int known_cipher_nids_amount = -1; /* -1 indicates not yet initialised */ +-static EVP_CIPHER *known_cipher_methods[OSSL_NELEM(cipher_data)] = { NULL, }; +-static int selected_ciphers[OSSL_NELEM(cipher_data)]; +-static struct driver_info_st cipher_driver_info[OSSL_NELEM(cipher_data)]; +- +- +-static int devcrypto_test_cipher(size_t cipher_data_index) +-{ +- return (cipher_driver_info[cipher_data_index].status == DEVCRYPTO_STATUS_USABLE +- && selected_ciphers[cipher_data_index] == 1 +- && (cipher_driver_info[cipher_data_index].accelerated +- == DEVCRYPTO_ACCELERATED +- || use_softdrivers == DEVCRYPTO_USE_SOFTWARE +- || (cipher_driver_info[cipher_data_index].accelerated +- != DEVCRYPTO_NOT_ACCELERATED +- && use_softdrivers == DEVCRYPTO_REJECT_SOFTWARE))); +-} +- +-static void prepare_cipher_methods(void) +-{ +- size_t i; +- struct session_op sess; +- unsigned long cipher_mode; +-#ifdef CIOCGSESSINFO +- struct session_info_op siop; +-#endif +- +- memset(&cipher_driver_info, 0, sizeof(cipher_driver_info)); +- +- memset(&sess, 0, sizeof(sess)); +- sess.key = (void *)"01234567890123456789012345678901234567890123456789"; +- +- for (i = 0, known_cipher_nids_amount = 0; +- i < OSSL_NELEM(cipher_data); i++) { +- +- selected_ciphers[i] = 1; +- /* +- * Check that the cipher is usable +- */ +- sess.cipher = cipher_data[i].devcryptoid; +- sess.keylen = cipher_data[i].keylen; +- if (ioctl(cfd, CIOCGSESSION, &sess) < 0) { +- cipher_driver_info[i].status = DEVCRYPTO_STATUS_NO_CIOCGSESSION; +- continue; +- } +- +- cipher_mode = cipher_data[i].flags & EVP_CIPH_MODE; +- +- if ((known_cipher_methods[i] = +- EVP_CIPHER_meth_new(cipher_data[i].nid, +- cipher_mode == EVP_CIPH_CTR_MODE ? 1 : +- cipher_data[i].blocksize, +- cipher_data[i].keylen)) == NULL +- || !EVP_CIPHER_meth_set_iv_length(known_cipher_methods[i], +- cipher_data[i].ivlen) +- || !EVP_CIPHER_meth_set_flags(known_cipher_methods[i], +- cipher_data[i].flags +- | EVP_CIPH_CUSTOM_COPY +- | EVP_CIPH_CTRL_INIT +- | EVP_CIPH_FLAG_DEFAULT_ASN1) +- || !EVP_CIPHER_meth_set_init(known_cipher_methods[i], cipher_init) +- || !EVP_CIPHER_meth_set_do_cipher(known_cipher_methods[i], +- cipher_mode == EVP_CIPH_CTR_MODE ? +- ctr_do_cipher : +- cipher_do_cipher) +- || !EVP_CIPHER_meth_set_ctrl(known_cipher_methods[i], cipher_ctrl) +- || !EVP_CIPHER_meth_set_cleanup(known_cipher_methods[i], +- cipher_cleanup) +- || !EVP_CIPHER_meth_set_impl_ctx_size(known_cipher_methods[i], +- sizeof(struct cipher_ctx))) { +- cipher_driver_info[i].status = DEVCRYPTO_STATUS_FAILURE; +- EVP_CIPHER_meth_free(known_cipher_methods[i]); +- known_cipher_methods[i] = NULL; +- } else { +- cipher_driver_info[i].status = DEVCRYPTO_STATUS_USABLE; +-#ifdef CIOCGSESSINFO +- siop.ses = sess.ses; +- if (ioctl(cfd, CIOCGSESSINFO, &siop) < 0) { +- cipher_driver_info[i].accelerated = DEVCRYPTO_ACCELERATION_UNKNOWN; +- } else { +- cipher_driver_info[i].driver_name = +- OPENSSL_strndup(siop.cipher_info.cra_driver_name, +- CRYPTODEV_MAX_ALG_NAME); +- if (!(siop.flags & SIOP_FLAG_KERNEL_DRIVER_ONLY)) +- cipher_driver_info[i].accelerated = DEVCRYPTO_NOT_ACCELERATED; +- else +- cipher_driver_info[i].accelerated = DEVCRYPTO_ACCELERATED; +- } +-#endif /* CIOCGSESSINFO */ +- } +- ioctl(cfd, CIOCFSESSION, &sess.ses); +- if (devcrypto_test_cipher(i)) { +- known_cipher_nids[known_cipher_nids_amount++] = +- cipher_data[i].nid; +- } +- } +-} +- +-static void rebuild_known_cipher_nids(ENGINE *e) +-{ +- size_t i; +- +- for (i = 0, known_cipher_nids_amount = 0; i < OSSL_NELEM(cipher_data); i++) { +- if (devcrypto_test_cipher(i)) +- known_cipher_nids[known_cipher_nids_amount++] = cipher_data[i].nid; +- } +- ENGINE_unregister_ciphers(e); +- ENGINE_register_ciphers(e); +-} +- +-static const EVP_CIPHER *get_cipher_method(int nid) +-{ +- size_t i = get_cipher_data_index(nid); +- +- if (i == (size_t)-1) +- return NULL; +- return known_cipher_methods[i]; +-} +- +-static int get_cipher_nids(const int **nids) +-{ +- *nids = known_cipher_nids; +- return known_cipher_nids_amount; +-} +- +-static void destroy_cipher_method(int nid) +-{ +- size_t i = get_cipher_data_index(nid); +- +- EVP_CIPHER_meth_free(known_cipher_methods[i]); +- known_cipher_methods[i] = NULL; +-} +- +-static void destroy_all_cipher_methods(void) +-{ +- size_t i; +- +- for (i = 0; i < OSSL_NELEM(cipher_data); i++) { +- destroy_cipher_method(cipher_data[i].nid); +- OPENSSL_free(cipher_driver_info[i].driver_name); +- cipher_driver_info[i].driver_name = NULL; +- } +-} +- +-static int devcrypto_ciphers(ENGINE *e, const EVP_CIPHER **cipher, +- const int **nids, int nid) +-{ +- if (cipher == NULL) +- return get_cipher_nids(nids); +- +- *cipher = get_cipher_method(nid); +- +- return *cipher != NULL; +-} +- +-static void devcrypto_select_all_ciphers(int *cipher_list) +-{ +- size_t i; +- +- for (i = 0; i < OSSL_NELEM(cipher_data); i++) +- cipher_list[i] = 1; +-} +- +-static int cryptodev_select_cipher_cb(const char *str, int len, void *usr) +-{ +- int *cipher_list = (int *)usr; +- char *name; +- const EVP_CIPHER *EVP; +- size_t i; +- +- if (len == 0) +- return 1; +- if (usr == NULL || (name = OPENSSL_strndup(str, len)) == NULL) +- return 0; +- EVP = EVP_get_cipherbyname(name); +- if (EVP == NULL) +- fprintf(stderr, "devcrypto: unknown cipher %s\n", name); +- else if ((i = find_cipher_data_index(EVP_CIPHER_nid(EVP))) != (size_t)-1) +- cipher_list[i] = 1; +- else +- fprintf(stderr, "devcrypto: cipher %s not available\n", name); +- OPENSSL_free(name); +- return 1; +-} +- +-static void dump_cipher_info(void) +-{ +- size_t i; +- const char *name; +- +- fprintf (stderr, "Information about ciphers supported by the /dev/crypto" +- " engine:\n"); +-#ifndef CIOCGSESSINFO +- fprintf(stderr, "CIOCGSESSINFO (session info call) unavailable\n"); +-#endif +- for (i = 0; i < OSSL_NELEM(cipher_data); i++) { +- name = OBJ_nid2sn(cipher_data[i].nid); +- fprintf (stderr, "Cipher %s, NID=%d, /dev/crypto info: id=%d, ", +- name ? name : "unknown", cipher_data[i].nid, +- cipher_data[i].devcryptoid); +- if (cipher_driver_info[i].status == DEVCRYPTO_STATUS_NO_CIOCGSESSION ) { +- fprintf (stderr, "CIOCGSESSION (session open call) failed\n"); +- continue; +- } +- fprintf (stderr, "driver=%s ", cipher_driver_info[i].driver_name ? +- cipher_driver_info[i].driver_name : "unknown"); +- if (cipher_driver_info[i].accelerated == DEVCRYPTO_ACCELERATED) +- fprintf(stderr, "(hw accelerated)"); +- else if (cipher_driver_info[i].accelerated == DEVCRYPTO_NOT_ACCELERATED) +- fprintf(stderr, "(software)"); +- else +- fprintf(stderr, "(acceleration status unknown)"); +- if (cipher_driver_info[i].status == DEVCRYPTO_STATUS_FAILURE) +- fprintf (stderr, ". Cipher setup failed"); +- fprintf(stderr, "\n"); +- } +- fprintf(stderr, "\n"); +-} +- +-/* +- * We only support digests if the cryptodev implementation supports multiple +- * data updates and session copying. Otherwise, we would be forced to maintain +- * a cache, which is perilous if there's a lot of data coming in (if someone +- * wants to checksum an OpenSSL tarball, for example). +- */ +-#if defined(CIOCCPHASH) && defined(COP_FLAG_UPDATE) && defined(COP_FLAG_FINAL) +-#define IMPLEMENT_DIGEST +- +-/****************************************************************************** +- * +- * Digests +- * +- * Because they all do the same basic operation, we have only one set of +- * method functions for them all to share, and a mapping table between +- * NIDs and cryptodev IDs, with all the necessary size data. +- * +- *****/ +- +-struct digest_ctx { +- struct session_op sess; +- /* This signals that the init function was called, not that it succeeded. */ +- int init_called; +- unsigned char digest_res[HASH_MAX_LEN]; +-}; +- +-static const struct digest_data_st { +- int nid; +- int blocksize; +- int digestlen; +- int devcryptoid; +-} digest_data[] = { +-#ifndef OPENSSL_NO_MD5 +- { NID_md5, /* MD5_CBLOCK */ 64, 16, CRYPTO_MD5 }, +-#endif +- { NID_sha1, SHA_CBLOCK, 20, CRYPTO_SHA1 }, +-#ifndef OPENSSL_NO_RMD160 +-# if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_RIPEMD160) +- { NID_ripemd160, /* RIPEMD160_CBLOCK */ 64, 20, CRYPTO_RIPEMD160 }, +-# endif +-#endif +-#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_224) +- { NID_sha224, SHA256_CBLOCK, 224 / 8, CRYPTO_SHA2_224 }, +-#endif +-#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_256) +- { NID_sha256, SHA256_CBLOCK, 256 / 8, CRYPTO_SHA2_256 }, +-#endif +-#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_384) +- { NID_sha384, SHA512_CBLOCK, 384 / 8, CRYPTO_SHA2_384 }, +-#endif +-#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_512) +- { NID_sha512, SHA512_CBLOCK, 512 / 8, CRYPTO_SHA2_512 }, +-#endif +-}; +- +-static size_t find_digest_data_index(int nid) +-{ +- size_t i; +- +- for (i = 0; i < OSSL_NELEM(digest_data); i++) +- if (nid == digest_data[i].nid) +- return i; +- return (size_t)-1; +-} +- +-static size_t get_digest_data_index(int nid) +-{ +- size_t i = find_digest_data_index(nid); +- +- if (i != (size_t)-1) +- return i; +- +- /* +- * Code further down must make sure that only NIDs in the table above +- * are used. If any other NID reaches this function, there's a grave +- * coding error further down. +- */ +- assert("Code that never should be reached" == NULL); +- return -1; +-} +- +-static const struct digest_data_st *get_digest_data(int nid) +-{ +- return &digest_data[get_digest_data_index(nid)]; +-} +- +-/* +- * Following are the five necessary functions to map OpenSSL functionality +- * with cryptodev: init, update, final, cleanup, and copy. +- */ +- +-static int digest_init(EVP_MD_CTX *ctx) +-{ +- struct digest_ctx *digest_ctx = +- (struct digest_ctx *)EVP_MD_CTX_md_data(ctx); +- const struct digest_data_st *digest_d = +- get_digest_data(EVP_MD_CTX_type(ctx)); +- +- digest_ctx->init_called = 1; +- +- memset(&digest_ctx->sess, 0, sizeof(digest_ctx->sess)); +- digest_ctx->sess.mac = digest_d->devcryptoid; +- if (ioctl(cfd, CIOCGSESSION, &digest_ctx->sess) < 0) { +- SYSerr(SYS_F_IOCTL, errno); +- return 0; +- } +- +- return 1; +-} +- +-static int digest_op(struct digest_ctx *ctx, const void *src, size_t srclen, +- void *res, unsigned int flags) +-{ +- struct crypt_op cryp; +- +- memset(&cryp, 0, sizeof(cryp)); +- cryp.ses = ctx->sess.ses; +- cryp.len = srclen; +- cryp.src = (void *)src; +- cryp.dst = NULL; +- cryp.mac = res; +- cryp.flags = flags; +- return ioctl(cfd, CIOCCRYPT, &cryp); +-} +- +-static int digest_update(EVP_MD_CTX *ctx, const void *data, size_t count) +-{ +- struct digest_ctx *digest_ctx = +- (struct digest_ctx *)EVP_MD_CTX_md_data(ctx); +- +- if (count == 0) +- return 1; +- +- if (digest_ctx == NULL) +- return 0; +- +- if (EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_ONESHOT)) { +- if (digest_op(digest_ctx, data, count, digest_ctx->digest_res, 0) >= 0) +- return 1; +- } else if (digest_op(digest_ctx, data, count, NULL, COP_FLAG_UPDATE) >= 0) { +- return 1; +- } +- +- SYSerr(SYS_F_IOCTL, errno); +- return 0; +-} +- +-static int digest_final(EVP_MD_CTX *ctx, unsigned char *md) +-{ +- struct digest_ctx *digest_ctx = +- (struct digest_ctx *)EVP_MD_CTX_md_data(ctx); +- +- if (md == NULL || digest_ctx == NULL) +- return 0; +- +- if (EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_ONESHOT)) { +- memcpy(md, digest_ctx->digest_res, EVP_MD_CTX_size(ctx)); +- } else if (digest_op(digest_ctx, NULL, 0, md, COP_FLAG_FINAL) < 0) { +- SYSerr(SYS_F_IOCTL, errno); +- return 0; +- } +- +- return 1; +-} +- +-static int digest_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from) +-{ +- struct digest_ctx *digest_from = +- (struct digest_ctx *)EVP_MD_CTX_md_data(from); +- struct digest_ctx *digest_to = +- (struct digest_ctx *)EVP_MD_CTX_md_data(to); +- struct cphash_op cphash; +- +- if (digest_from == NULL || digest_from->init_called != 1) +- return 1; +- +- if (!digest_init(to)) { +- SYSerr(SYS_F_IOCTL, errno); +- return 0; +- } +- +- cphash.src_ses = digest_from->sess.ses; +- cphash.dst_ses = digest_to->sess.ses; +- if (ioctl(cfd, CIOCCPHASH, &cphash) < 0) { +- SYSerr(SYS_F_IOCTL, errno); +- return 0; +- } +- return 1; +-} +- +-static int digest_cleanup(EVP_MD_CTX *ctx) +-{ +- struct digest_ctx *digest_ctx = +- (struct digest_ctx *)EVP_MD_CTX_md_data(ctx); +- +- if (digest_ctx == NULL) +- return 1; +- +- return clean_devcrypto_session(&digest_ctx->sess); +-} +- +-/* +- * Keep tables of known nids, associated methods, selected digests, and +- * driver info. +- * Note that known_digest_nids[] isn't necessarily indexed the same way as +- * digest_data[] above, which the other tables are. +- */ +-static int known_digest_nids[OSSL_NELEM(digest_data)]; +-static int known_digest_nids_amount = -1; /* -1 indicates not yet initialised */ +-static EVP_MD *known_digest_methods[OSSL_NELEM(digest_data)] = { NULL, }; +-static int selected_digests[OSSL_NELEM(digest_data)]; +-static struct driver_info_st digest_driver_info[OSSL_NELEM(digest_data)]; +- +-static int devcrypto_test_digest(size_t digest_data_index) +-{ +- return (digest_driver_info[digest_data_index].status == DEVCRYPTO_STATUS_USABLE +- && selected_digests[digest_data_index] == 1 +- && (digest_driver_info[digest_data_index].accelerated +- == DEVCRYPTO_ACCELERATED +- || use_softdrivers == DEVCRYPTO_USE_SOFTWARE +- || (digest_driver_info[digest_data_index].accelerated +- != DEVCRYPTO_NOT_ACCELERATED +- && use_softdrivers == DEVCRYPTO_REJECT_SOFTWARE))); +-} +- +-static void rebuild_known_digest_nids(ENGINE *e) +-{ +- size_t i; +- +- for (i = 0, known_digest_nids_amount = 0; i < OSSL_NELEM(digest_data); i++) { +- if (devcrypto_test_digest(i)) +- known_digest_nids[known_digest_nids_amount++] = digest_data[i].nid; +- } +- ENGINE_unregister_digests(e); +- ENGINE_register_digests(e); +-} +- +-static void prepare_digest_methods(void) +-{ +- size_t i; +- struct session_op sess1, sess2; +-#ifdef CIOCGSESSINFO +- struct session_info_op siop; +-#endif +- struct cphash_op cphash; +- +- memset(&digest_driver_info, 0, sizeof(digest_driver_info)); +- +- memset(&sess1, 0, sizeof(sess1)); +- memset(&sess2, 0, sizeof(sess2)); +- +- for (i = 0, known_digest_nids_amount = 0; i < OSSL_NELEM(digest_data); +- i++) { +- +- selected_digests[i] = 1; +- +- /* +- * Check that the digest is usable +- */ +- sess1.mac = digest_data[i].devcryptoid; +- sess2.ses = 0; +- if (ioctl(cfd, CIOCGSESSION, &sess1) < 0) { +- digest_driver_info[i].status = DEVCRYPTO_STATUS_NO_CIOCGSESSION; +- goto finish; +- } +- +-#ifdef CIOCGSESSINFO +- /* gather hardware acceleration info from the driver */ +- siop.ses = sess1.ses; +- if (ioctl(cfd, CIOCGSESSINFO, &siop) < 0) { +- digest_driver_info[i].accelerated = DEVCRYPTO_ACCELERATION_UNKNOWN; +- } else { +- digest_driver_info[i].driver_name = +- OPENSSL_strndup(siop.hash_info.cra_driver_name, +- CRYPTODEV_MAX_ALG_NAME); +- if (siop.flags & SIOP_FLAG_KERNEL_DRIVER_ONLY) +- digest_driver_info[i].accelerated = DEVCRYPTO_ACCELERATED; +- else +- digest_driver_info[i].accelerated = DEVCRYPTO_NOT_ACCELERATED; +- } +-#endif +- +- /* digest must be capable of hash state copy */ +- sess2.mac = sess1.mac; +- if (ioctl(cfd, CIOCGSESSION, &sess2) < 0) { +- digest_driver_info[i].status = DEVCRYPTO_STATUS_FAILURE; +- goto finish; +- } +- cphash.src_ses = sess1.ses; +- cphash.dst_ses = sess2.ses; +- if (ioctl(cfd, CIOCCPHASH, &cphash) < 0) { +- digest_driver_info[i].status = DEVCRYPTO_STATUS_NO_CIOCCPHASH; +- goto finish; +- } +- if ((known_digest_methods[i] = EVP_MD_meth_new(digest_data[i].nid, +- NID_undef)) == NULL +- || !EVP_MD_meth_set_input_blocksize(known_digest_methods[i], +- digest_data[i].blocksize) +- || !EVP_MD_meth_set_result_size(known_digest_methods[i], +- digest_data[i].digestlen) +- || !EVP_MD_meth_set_init(known_digest_methods[i], digest_init) +- || !EVP_MD_meth_set_update(known_digest_methods[i], digest_update) +- || !EVP_MD_meth_set_final(known_digest_methods[i], digest_final) +- || !EVP_MD_meth_set_copy(known_digest_methods[i], digest_copy) +- || !EVP_MD_meth_set_cleanup(known_digest_methods[i], digest_cleanup) +- || !EVP_MD_meth_set_app_datasize(known_digest_methods[i], +- sizeof(struct digest_ctx))) { +- digest_driver_info[i].status = DEVCRYPTO_STATUS_FAILURE; +- EVP_MD_meth_free(known_digest_methods[i]); +- known_digest_methods[i] = NULL; +- goto finish; +- } +- digest_driver_info[i].status = DEVCRYPTO_STATUS_USABLE; +-finish: +- ioctl(cfd, CIOCFSESSION, &sess1.ses); +- if (sess2.ses != 0) +- ioctl(cfd, CIOCFSESSION, &sess2.ses); +- if (devcrypto_test_digest(i)) +- known_digest_nids[known_digest_nids_amount++] = digest_data[i].nid; +- } +-} +- +-static const EVP_MD *get_digest_method(int nid) +-{ +- size_t i = get_digest_data_index(nid); +- +- if (i == (size_t)-1) +- return NULL; +- return known_digest_methods[i]; +-} +- +-static int get_digest_nids(const int **nids) +-{ +- *nids = known_digest_nids; +- return known_digest_nids_amount; +-} +- +-static void destroy_digest_method(int nid) +-{ +- size_t i = get_digest_data_index(nid); +- +- EVP_MD_meth_free(known_digest_methods[i]); +- known_digest_methods[i] = NULL; +-} +- +-static void destroy_all_digest_methods(void) +-{ +- size_t i; +- +- for (i = 0; i < OSSL_NELEM(digest_data); i++) { +- destroy_digest_method(digest_data[i].nid); +- OPENSSL_free(digest_driver_info[i].driver_name); +- digest_driver_info[i].driver_name = NULL; +- } +-} +- +-static int devcrypto_digests(ENGINE *e, const EVP_MD **digest, +- const int **nids, int nid) +-{ +- if (digest == NULL) +- return get_digest_nids(nids); +- +- *digest = get_digest_method(nid); +- +- return *digest != NULL; +-} +- +-static void devcrypto_select_all_digests(int *digest_list) +-{ +- size_t i; +- +- for (i = 0; i < OSSL_NELEM(digest_data); i++) +- digest_list[i] = 1; +-} +- +-static int cryptodev_select_digest_cb(const char *str, int len, void *usr) +-{ +- int *digest_list = (int *)usr; +- char *name; +- const EVP_MD *EVP; +- size_t i; +- +- if (len == 0) +- return 1; +- if (usr == NULL || (name = OPENSSL_strndup(str, len)) == NULL) +- return 0; +- EVP = EVP_get_digestbyname(name); +- if (EVP == NULL) +- fprintf(stderr, "devcrypto: unknown digest %s\n", name); +- else if ((i = find_digest_data_index(EVP_MD_type(EVP))) != (size_t)-1) +- digest_list[i] = 1; +- else +- fprintf(stderr, "devcrypto: digest %s not available\n", name); +- OPENSSL_free(name); +- return 1; +-} +- +-static void dump_digest_info(void) +-{ +- size_t i; +- const char *name; +- +- fprintf (stderr, "Information about digests supported by the /dev/crypto" +- " engine:\n"); +-#ifndef CIOCGSESSINFO +- fprintf(stderr, "CIOCGSESSINFO (session info call) unavailable\n"); +-#endif +- +- for (i = 0; i < OSSL_NELEM(digest_data); i++) { +- name = OBJ_nid2sn(digest_data[i].nid); +- fprintf (stderr, "Digest %s, NID=%d, /dev/crypto info: id=%d, driver=%s", +- name ? name : "unknown", digest_data[i].nid, +- digest_data[i].devcryptoid, +- digest_driver_info[i].driver_name ? digest_driver_info[i].driver_name : "unknown"); +- if (digest_driver_info[i].status == DEVCRYPTO_STATUS_NO_CIOCGSESSION) { +- fprintf (stderr, ". CIOCGSESSION (session open) failed\n"); +- continue; +- } +- if (digest_driver_info[i].accelerated == DEVCRYPTO_ACCELERATED) +- fprintf(stderr, " (hw accelerated)"); +- else if (digest_driver_info[i].accelerated == DEVCRYPTO_NOT_ACCELERATED) +- fprintf(stderr, " (software)"); +- else +- fprintf(stderr, " (acceleration status unknown)"); +- if (cipher_driver_info[i].status == DEVCRYPTO_STATUS_FAILURE) +- fprintf (stderr, ". Cipher setup failed\n"); +- else if (digest_driver_info[i].status == DEVCRYPTO_STATUS_NO_CIOCCPHASH) +- fprintf(stderr, ", CIOCCPHASH failed\n"); +- else +- fprintf(stderr, ", CIOCCPHASH capable\n"); +- } +- fprintf(stderr, "\n"); +-} +- +-#endif +- +-/****************************************************************************** +- * +- * CONTROL COMMANDS +- * +- *****/ +- +-#define DEVCRYPTO_CMD_USE_SOFTDRIVERS ENGINE_CMD_BASE +-#define DEVCRYPTO_CMD_CIPHERS (ENGINE_CMD_BASE + 1) +-#define DEVCRYPTO_CMD_DIGESTS (ENGINE_CMD_BASE + 2) +-#define DEVCRYPTO_CMD_DUMP_INFO (ENGINE_CMD_BASE + 3) +- +-/* Helper macros for CPP string composition */ +-#ifndef OPENSSL_MSTR +-# define OPENSSL_MSTR_HELPER(x) #x +-# define OPENSSL_MSTR(x) OPENSSL_MSTR_HELPER(x) +-#endif +- +-static const ENGINE_CMD_DEFN devcrypto_cmds[] = { +-#ifdef CIOCGSESSINFO +- {DEVCRYPTO_CMD_USE_SOFTDRIVERS, +- "USE_SOFTDRIVERS", +- "specifies whether to use software (not accelerated) drivers (" +- OPENSSL_MSTR(DEVCRYPTO_REQUIRE_ACCELERATED) "=use only accelerated drivers, " +- OPENSSL_MSTR(DEVCRYPTO_USE_SOFTWARE) "=allow all drivers, " +- OPENSSL_MSTR(DEVCRYPTO_REJECT_SOFTWARE) +- "=use if acceleration can't be determined) [default=" - OPENSSL_MSTR(DEVCRYPTO_DEFAULT_USE_SOFDTRIVERS) "]", -+ OPENSSL_MSTR(DEVCRYPTO_DEFAULT_USE_SOFTDRIVERS) "]", - ENGINE_CMD_FLAG_NUMERIC}, - #endif - -@@ -1166,55 +1168,70 @@ static int devcrypto_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void)) - * - *****/ - +- ENGINE_CMD_FLAG_NUMERIC}, +-#endif +- +- {DEVCRYPTO_CMD_CIPHERS, +- "CIPHERS", +- "either ALL, NONE, or a comma-separated list of ciphers to enable [default=ALL]", +- ENGINE_CMD_FLAG_STRING}, +- +-#ifdef IMPLEMENT_DIGEST +- {DEVCRYPTO_CMD_DIGESTS, +- "DIGESTS", +- "either ALL, NONE, or a comma-separated list of digests to enable [default=ALL]", +- ENGINE_CMD_FLAG_STRING}, +-#endif +- +- {DEVCRYPTO_CMD_DUMP_INFO, +- "DUMP_INFO", +- "dump info about each algorithm to stderr; use 'openssl engine -pre DUMP_INFO devcrypto'", +- ENGINE_CMD_FLAG_NO_INPUT}, +- +- {0, NULL, NULL, 0} +-}; +- +-static int devcrypto_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void)) +-{ +- int *new_list; +- switch (cmd) { +-#ifdef CIOCGSESSINFO +- case DEVCRYPTO_CMD_USE_SOFTDRIVERS: +- switch (i) { +- case DEVCRYPTO_REQUIRE_ACCELERATED: +- case DEVCRYPTO_USE_SOFTWARE: +- case DEVCRYPTO_REJECT_SOFTWARE: +- break; +- default: +- fprintf(stderr, "devcrypto: invalid value (%ld) for USE_SOFTDRIVERS\n", i); +- return 0; +- } +- if (use_softdrivers == i) +- return 1; +- use_softdrivers = i; +-#ifdef IMPLEMENT_DIGEST +- rebuild_known_digest_nids(e); +-#endif +- rebuild_known_cipher_nids(e); +- return 1; +-#endif /* CIOCGSESSINFO */ +- +- case DEVCRYPTO_CMD_CIPHERS: +- if (p == NULL) +- return 1; +- if (strcasecmp((const char *)p, "ALL") == 0) { +- devcrypto_select_all_ciphers(selected_ciphers); +- } else if (strcasecmp((const char*)p, "NONE") == 0) { +- memset(selected_ciphers, 0, sizeof(selected_ciphers)); +- } else { +- new_list=OPENSSL_zalloc(sizeof(selected_ciphers)); +- if (!CONF_parse_list(p, ',', 1, cryptodev_select_cipher_cb, new_list)) { +- OPENSSL_free(new_list); +- return 0; +- } +- memcpy(selected_ciphers, new_list, sizeof(selected_ciphers)); +- OPENSSL_free(new_list); +- } +- rebuild_known_cipher_nids(e); +- return 1; +- +-#ifdef IMPLEMENT_DIGEST +- case DEVCRYPTO_CMD_DIGESTS: +- if (p == NULL) +- return 1; +- if (strcasecmp((const char *)p, "ALL") == 0) { +- devcrypto_select_all_digests(selected_digests); +- } else if (strcasecmp((const char*)p, "NONE") == 0) { +- memset(selected_digests, 0, sizeof(selected_digests)); +- } else { +- new_list=OPENSSL_zalloc(sizeof(selected_digests)); +- if (!CONF_parse_list(p, ',', 1, cryptodev_select_digest_cb, new_list)) { +- OPENSSL_free(new_list); +- return 0; +- } +- memcpy(selected_digests, new_list, sizeof(selected_digests)); +- OPENSSL_free(new_list); +- } +- rebuild_known_digest_nids(e); +- return 1; +-#endif /* IMPLEMENT_DIGEST */ +- +- case DEVCRYPTO_CMD_DUMP_INFO: +- dump_cipher_info(); +-#ifdef IMPLEMENT_DIGEST +- dump_digest_info(); +-#endif +- return 1; +- +- default: +- break; +- } +- return 0; +-} +- +-/****************************************************************************** +- * +- * LOAD / UNLOAD +- * +- *****/ +- -static int devcrypto_unload(ENGINE *e) -{ - destroy_all_cipher_methods(); @@ -192,27 +1288,22 @@ index 0d420e50aa..3fcd81de7a 100644 - - return 1; -} - /* +-/* - * This engine is always built into libcrypto, so it doesn't offer any - * ability to be dynamically loadable. -+ * Opens /dev/crypto - */ +- */ -void engine_load_devcrypto_int() -+static int open_devcrypto(void) - { +-{ - ENGINE *e = NULL; -+ if (cfd >= 0) -+ return 1; - - if ((cfd = open("/dev/crypto", O_RDWR, 0)) < 0) { - #ifndef ENGINE_DEVCRYPTO_DEBUG - if (errno != ENOENT) - #endif - fprintf(stderr, "Could not open /dev/crypto: %s\n", strerror(errno)); +- +- if ((cfd = open("/dev/crypto", O_RDWR, 0)) < 0) { +-#ifndef ENGINE_DEVCRYPTO_DEBUG +- if (errno != ENOENT) +-#endif +- fprintf(stderr, "Could not open /dev/crypto: %s\n", strerror(errno)); - return; -+ return 0; - } - +- } +- - if ((e = ENGINE_new()) == NULL - || !ENGINE_set_destroy_function(e, devcrypto_unload)) { - ENGINE_free(e); @@ -223,6 +1314,1254 @@ index 0d420e50aa..3fcd81de7a 100644 - */ - close(cfd); - return; +- } +- +- prepare_cipher_methods(); +-#ifdef IMPLEMENT_DIGEST +- prepare_digest_methods(); +-#endif +- +- if (!ENGINE_set_id(e, "devcrypto") +- || !ENGINE_set_name(e, "/dev/crypto engine") +- || !ENGINE_set_cmd_defns(e, devcrypto_cmds) +- || !ENGINE_set_ctrl_function(e, devcrypto_ctrl) +- +-/* +- * Asymmetric ciphers aren't well supported with /dev/crypto. Among the BSD +- * implementations, it seems to only exist in FreeBSD, and regarding the +- * parameters in its crypt_kop, the manual crypto(4) has this to say: +- * +- * The semantics of these arguments are currently undocumented. +- * +- * Reading through the FreeBSD source code doesn't give much more than +- * their CRK_MOD_EXP implementation for ubsec. +- * +- * It doesn't look much better with cryptodev-linux. They have the crypt_kop +- * structure as well as the command (CRK_*) in cryptodev.h, but no support +- * seems to be implemented at all for the moment. +- * +- * At the time of writing, it seems impossible to write proper support for +- * FreeBSD's asym features without some very deep knowledge and access to +- * specific kernel modules. +- * +- * /Richard Levitte, 2017-05-11 +- */ +-#if 0 +-# ifndef OPENSSL_NO_RSA +- || !ENGINE_set_RSA(e, devcrypto_rsa) +-# endif +-# ifndef OPENSSL_NO_DSA +- || !ENGINE_set_DSA(e, devcrypto_dsa) +-# endif +-# ifndef OPENSSL_NO_DH +- || !ENGINE_set_DH(e, devcrypto_dh) +-# endif +-# ifndef OPENSSL_NO_EC +- || !ENGINE_set_EC(e, devcrypto_ec) +-# endif +-#endif +- || !ENGINE_set_ciphers(e, devcrypto_ciphers) +-#ifdef IMPLEMENT_DIGEST +- || !ENGINE_set_digests(e, devcrypto_digests) +-#endif +- ) { +- ENGINE_free(e); +- return; +- } +- +- ENGINE_add(e); +- ENGINE_free(e); /* Loose our local reference */ +- ERR_clear_error(); +-} +--- /dev/null ++++ b/engines/e_devcrypto.c +@@ -0,0 +1,1313 @@ ++/* ++ * Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved. ++ * ++ * Licensed under the OpenSSL license (the "License"). You may not use ++ * this file except in compliance with the License. You can obtain a copy ++ * in the file LICENSE in the source distribution or at ++ * https://www.openssl.org/source/license.html ++ */ ++ ++#include "../e_os.h" ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "crypto/engine.h" ++ ++/* #define ENGINE_DEVCRYPTO_DEBUG */ ++ ++#if CRYPTO_ALGORITHM_MIN < CRYPTO_ALGORITHM_MAX ++# define CHECK_BSD_STYLE_MACROS ++#endif ++ ++#define engine_devcrypto_id "devcrypto" ++ ++/* ++ * ONE global file descriptor for all sessions. This allows operations ++ * such as digest session data copying (see digest_copy()), but is also ++ * saner... why re-open /dev/crypto for every session? ++ */ ++static int cfd = -1; ++#define DEVCRYPTO_REQUIRE_ACCELERATED 0 /* require confirmation of acceleration */ ++#define DEVCRYPTO_USE_SOFTWARE 1 /* allow software drivers */ ++#define DEVCRYPTO_REJECT_SOFTWARE 2 /* only disallow confirmed software drivers */ ++ ++#define DEVCRYPTO_DEFAULT_USE_SOFTDRIVERS DEVCRYPTO_REJECT_SOFTWARE ++static int use_softdrivers = DEVCRYPTO_DEFAULT_USE_SOFTDRIVERS; ++ ++/* ++ * cipher/digest status & acceleration definitions ++ * Make sure the defaults are set to 0 ++ */ ++struct driver_info_st { ++ enum devcrypto_status_t { ++ DEVCRYPTO_STATUS_FAILURE = -3, /* unusable for other reason */ ++ DEVCRYPTO_STATUS_NO_CIOCCPHASH = -2, /* hash state copy not supported */ ++ DEVCRYPTO_STATUS_NO_CIOCGSESSION = -1, /* session open failed */ ++ DEVCRYPTO_STATUS_UNKNOWN = 0, /* not tested yet */ ++ DEVCRYPTO_STATUS_USABLE = 1 /* algo can be used */ ++ } status; ++ ++ enum devcrypto_accelerated_t { ++ DEVCRYPTO_NOT_ACCELERATED = -1, /* software implemented */ ++ DEVCRYPTO_ACCELERATION_UNKNOWN = 0, /* acceleration support unkown */ ++ DEVCRYPTO_ACCELERATED = 1 /* hardware accelerated */ ++ } accelerated; ++ ++ char *driver_name; ++}; ++ ++static int clean_devcrypto_session(struct session_op *sess) { ++ if (ioctl(cfd, CIOCFSESSION, &sess->ses) < 0) { ++ SYSerr(SYS_F_IOCTL, errno); ++ return 0; ++ } ++ memset(sess, 0, sizeof(struct session_op)); ++ return 1; ++} ++ ++/****************************************************************************** ++ * ++ * Ciphers ++ * ++ * Because they all do the same basic operation, we have only one set of ++ * method functions for them all to share, and a mapping table between ++ * NIDs and cryptodev IDs, with all the necessary size data. ++ * ++ *****/ ++ ++struct cipher_ctx { ++ struct session_op sess; ++ int op; /* COP_ENCRYPT or COP_DECRYPT */ ++ unsigned long mode; /* EVP_CIPH_*_MODE */ ++ ++ /* to handle ctr mode being a stream cipher */ ++ unsigned char partial[EVP_MAX_BLOCK_LENGTH]; ++ unsigned int blocksize, num; ++}; ++ ++static const struct cipher_data_st { ++ int nid; ++ int blocksize; ++ int keylen; ++ int ivlen; ++ int flags; ++ int devcryptoid; ++} cipher_data[] = { ++#ifndef OPENSSL_NO_DES ++ { NID_des_cbc, 8, 8, 8, EVP_CIPH_CBC_MODE, CRYPTO_DES_CBC }, ++ { NID_des_ede3_cbc, 8, 24, 8, EVP_CIPH_CBC_MODE, CRYPTO_3DES_CBC }, ++#endif ++#ifndef OPENSSL_NO_BF ++ { NID_bf_cbc, 8, 16, 8, EVP_CIPH_CBC_MODE, CRYPTO_BLF_CBC }, ++#endif ++#ifndef OPENSSL_NO_CAST ++ { NID_cast5_cbc, 8, 16, 8, EVP_CIPH_CBC_MODE, CRYPTO_CAST_CBC }, ++#endif ++ { NID_aes_128_cbc, 16, 128 / 8, 16, EVP_CIPH_CBC_MODE, CRYPTO_AES_CBC }, ++ { NID_aes_192_cbc, 16, 192 / 8, 16, EVP_CIPH_CBC_MODE, CRYPTO_AES_CBC }, ++ { NID_aes_256_cbc, 16, 256 / 8, 16, EVP_CIPH_CBC_MODE, CRYPTO_AES_CBC }, ++#ifndef OPENSSL_NO_RC4 ++ { NID_rc4, 1, 16, 0, EVP_CIPH_STREAM_CIPHER, CRYPTO_ARC4 }, ++#endif ++#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_AES_CTR) ++ { NID_aes_128_ctr, 16, 128 / 8, 16, EVP_CIPH_CTR_MODE, CRYPTO_AES_CTR }, ++ { NID_aes_192_ctr, 16, 192 / 8, 16, EVP_CIPH_CTR_MODE, CRYPTO_AES_CTR }, ++ { NID_aes_256_ctr, 16, 256 / 8, 16, EVP_CIPH_CTR_MODE, CRYPTO_AES_CTR }, ++#endif ++#if 0 /* Not yet supported */ ++ { NID_aes_128_xts, 16, 128 / 8 * 2, 16, EVP_CIPH_XTS_MODE, CRYPTO_AES_XTS }, ++ { NID_aes_256_xts, 16, 256 / 8 * 2, 16, EVP_CIPH_XTS_MODE, CRYPTO_AES_XTS }, ++#endif ++#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_AES_ECB) ++ { NID_aes_128_ecb, 16, 128 / 8, 0, EVP_CIPH_ECB_MODE, CRYPTO_AES_ECB }, ++ { NID_aes_192_ecb, 16, 192 / 8, 0, EVP_CIPH_ECB_MODE, CRYPTO_AES_ECB }, ++ { NID_aes_256_ecb, 16, 256 / 8, 0, EVP_CIPH_ECB_MODE, CRYPTO_AES_ECB }, ++#endif ++#if 0 /* Not yet supported */ ++ { NID_aes_128_gcm, 16, 128 / 8, 16, EVP_CIPH_GCM_MODE, CRYPTO_AES_GCM }, ++ { NID_aes_192_gcm, 16, 192 / 8, 16, EVP_CIPH_GCM_MODE, CRYPTO_AES_GCM }, ++ { NID_aes_256_gcm, 16, 256 / 8, 16, EVP_CIPH_GCM_MODE, CRYPTO_AES_GCM }, ++#endif ++#ifndef OPENSSL_NO_CAMELLIA ++ { NID_camellia_128_cbc, 16, 128 / 8, 16, EVP_CIPH_CBC_MODE, ++ CRYPTO_CAMELLIA_CBC }, ++ { NID_camellia_192_cbc, 16, 192 / 8, 16, EVP_CIPH_CBC_MODE, ++ CRYPTO_CAMELLIA_CBC }, ++ { NID_camellia_256_cbc, 16, 256 / 8, 16, EVP_CIPH_CBC_MODE, ++ CRYPTO_CAMELLIA_CBC }, ++#endif ++}; ++ ++static size_t find_cipher_data_index(int nid) ++{ ++ size_t i; ++ ++ for (i = 0; i < OSSL_NELEM(cipher_data); i++) ++ if (nid == cipher_data[i].nid) ++ return i; ++ return (size_t)-1; ++} ++ ++static size_t get_cipher_data_index(int nid) ++{ ++ size_t i = find_cipher_data_index(nid); ++ ++ if (i != (size_t)-1) ++ return i; ++ ++ /* ++ * Code further down must make sure that only NIDs in the table above ++ * are used. If any other NID reaches this function, there's a grave ++ * coding error further down. ++ */ ++ assert("Code that never should be reached" == NULL); ++ return -1; ++} ++ ++static const struct cipher_data_st *get_cipher_data(int nid) ++{ ++ return &cipher_data[get_cipher_data_index(nid)]; ++} ++ ++/* ++ * Following are the three necessary functions to map OpenSSL functionality ++ * with cryptodev. ++ */ ++ ++static int cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, ++ const unsigned char *iv, int enc) ++{ ++ struct cipher_ctx *cipher_ctx = ++ (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx); ++ const struct cipher_data_st *cipher_d = ++ get_cipher_data(EVP_CIPHER_CTX_nid(ctx)); ++ ++ /* cleanup a previous session */ ++ if (cipher_ctx->sess.ses != 0 && ++ clean_devcrypto_session(&cipher_ctx->sess) == 0) ++ return 0; ++ ++ cipher_ctx->sess.cipher = cipher_d->devcryptoid; ++ cipher_ctx->sess.keylen = cipher_d->keylen; ++ cipher_ctx->sess.key = (void *)key; ++ cipher_ctx->op = enc ? COP_ENCRYPT : COP_DECRYPT; ++ cipher_ctx->mode = cipher_d->flags & EVP_CIPH_MODE; ++ cipher_ctx->blocksize = cipher_d->blocksize; ++ if (ioctl(cfd, CIOCGSESSION, &cipher_ctx->sess) < 0) { ++ SYSerr(SYS_F_IOCTL, errno); ++ return 0; ++ } ++ ++ return 1; ++} ++ ++static int cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, ++ const unsigned char *in, size_t inl) ++{ ++ struct cipher_ctx *cipher_ctx = ++ (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx); ++ struct crypt_op cryp; ++ unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx); ++#if !defined(COP_FLAG_WRITE_IV) ++ unsigned char saved_iv[EVP_MAX_IV_LENGTH]; ++ const unsigned char *ivptr; ++ size_t nblocks, ivlen; ++#endif ++ ++ memset(&cryp, 0, sizeof(cryp)); ++ cryp.ses = cipher_ctx->sess.ses; ++ cryp.len = inl; ++ cryp.src = (void *)in; ++ cryp.dst = (void *)out; ++ cryp.iv = (void *)iv; ++ cryp.op = cipher_ctx->op; ++#if !defined(COP_FLAG_WRITE_IV) ++ cryp.flags = 0; ++ ++ ivlen = EVP_CIPHER_CTX_iv_length(ctx); ++ if (ivlen > 0) ++ switch (cipher_ctx->mode) { ++ case EVP_CIPH_CBC_MODE: ++ assert(inl >= ivlen); ++ if (!EVP_CIPHER_CTX_encrypting(ctx)) { ++ ivptr = in + inl - ivlen; ++ memcpy(saved_iv, ivptr, ivlen); ++ } ++ break; ++ ++ case EVP_CIPH_CTR_MODE: ++ break; ++ ++ default: /* should not happen */ ++ return 0; ++ } ++#else ++ cryp.flags = COP_FLAG_WRITE_IV; ++#endif ++ ++ if (ioctl(cfd, CIOCCRYPT, &cryp) < 0) { ++ SYSerr(SYS_F_IOCTL, errno); ++ return 0; ++ } ++ ++#if !defined(COP_FLAG_WRITE_IV) ++ if (ivlen > 0) ++ switch (cipher_ctx->mode) { ++ case EVP_CIPH_CBC_MODE: ++ assert(inl >= ivlen); ++ if (EVP_CIPHER_CTX_encrypting(ctx)) ++ ivptr = out + inl - ivlen; ++ else ++ ivptr = saved_iv; ++ ++ memcpy(iv, ivptr, ivlen); ++ break; ++ ++ case EVP_CIPH_CTR_MODE: ++ nblocks = (inl + cipher_ctx->blocksize - 1) ++ / cipher_ctx->blocksize; ++ do { ++ ivlen--; ++ nblocks += iv[ivlen]; ++ iv[ivlen] = (uint8_t) nblocks; ++ nblocks >>= 8; ++ } while (ivlen); ++ break; ++ ++ default: /* should not happen */ ++ return 0; ++ } ++#endif ++ ++ return 1; ++} ++ ++static int ctr_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, ++ const unsigned char *in, size_t inl) ++{ ++ struct cipher_ctx *cipher_ctx = ++ (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx); ++ size_t nblocks, len; ++ ++ /* initial partial block */ ++ while (cipher_ctx->num && inl) { ++ (*out++) = *(in++) ^ cipher_ctx->partial[cipher_ctx->num]; ++ --inl; ++ cipher_ctx->num = (cipher_ctx->num + 1) % cipher_ctx->blocksize; ++ } ++ ++ /* full blocks */ ++ if (inl > (unsigned int) cipher_ctx->blocksize) { ++ nblocks = inl/cipher_ctx->blocksize; ++ len = nblocks * cipher_ctx->blocksize; ++ if (cipher_do_cipher(ctx, out, in, len) < 1) ++ return 0; ++ inl -= len; ++ out += len; ++ in += len; ++ } ++ ++ /* final partial block */ ++ if (inl) { ++ memset(cipher_ctx->partial, 0, cipher_ctx->blocksize); ++ if (cipher_do_cipher(ctx, cipher_ctx->partial, cipher_ctx->partial, ++ cipher_ctx->blocksize) < 1) ++ return 0; ++ while (inl--) { ++ out[cipher_ctx->num] = in[cipher_ctx->num] ++ ^ cipher_ctx->partial[cipher_ctx->num]; ++ cipher_ctx->num++; ++ } ++ } ++ ++ return 1; ++} ++ ++static int cipher_ctrl(EVP_CIPHER_CTX *ctx, int type, int p1, void* p2) ++{ ++ struct cipher_ctx *cipher_ctx = ++ (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx); ++ EVP_CIPHER_CTX *to_ctx = (EVP_CIPHER_CTX *)p2; ++ struct cipher_ctx *to_cipher_ctx; ++ ++ switch (type) { ++ ++ case EVP_CTRL_COPY: ++ if (cipher_ctx == NULL) ++ return 1; ++ /* when copying the context, a new session needs to be initialized */ ++ to_cipher_ctx = ++ (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(to_ctx); ++ memset(&to_cipher_ctx->sess, 0, sizeof(to_cipher_ctx->sess)); ++ return cipher_init(to_ctx, cipher_ctx->sess.key, EVP_CIPHER_CTX_iv(ctx), ++ (cipher_ctx->op == COP_ENCRYPT)); ++ ++ case EVP_CTRL_INIT: ++ memset(&cipher_ctx->sess, 0, sizeof(cipher_ctx->sess)); ++ return 1; ++ ++ default: ++ break; ++ } ++ ++ return -1; ++} ++ ++static int cipher_cleanup(EVP_CIPHER_CTX *ctx) ++{ ++ struct cipher_ctx *cipher_ctx = ++ (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx); ++ ++ return clean_devcrypto_session(&cipher_ctx->sess); ++} ++ ++/* ++ * Keep tables of known nids, associated methods, selected ciphers, and driver ++ * info. ++ * Note that known_cipher_nids[] isn't necessarily indexed the same way as ++ * cipher_data[] above, which the other tables are. ++ */ ++static int known_cipher_nids[OSSL_NELEM(cipher_data)]; ++static int known_cipher_nids_amount = -1; /* -1 indicates not yet initialised */ ++static EVP_CIPHER *known_cipher_methods[OSSL_NELEM(cipher_data)] = { NULL, }; ++static int selected_ciphers[OSSL_NELEM(cipher_data)]; ++static struct driver_info_st cipher_driver_info[OSSL_NELEM(cipher_data)]; ++ ++ ++static int devcrypto_test_cipher(size_t cipher_data_index) ++{ ++ return (cipher_driver_info[cipher_data_index].status == DEVCRYPTO_STATUS_USABLE ++ && selected_ciphers[cipher_data_index] == 1 ++ && (cipher_driver_info[cipher_data_index].accelerated ++ == DEVCRYPTO_ACCELERATED ++ || use_softdrivers == DEVCRYPTO_USE_SOFTWARE ++ || (cipher_driver_info[cipher_data_index].accelerated ++ != DEVCRYPTO_NOT_ACCELERATED ++ && use_softdrivers == DEVCRYPTO_REJECT_SOFTWARE))); ++} ++ ++static void prepare_cipher_methods(void) ++{ ++ size_t i; ++ struct session_op sess; ++ unsigned long cipher_mode; ++#ifdef CIOCGSESSINFO ++ struct session_info_op siop; ++#endif ++ ++ memset(&cipher_driver_info, 0, sizeof(cipher_driver_info)); ++ ++ memset(&sess, 0, sizeof(sess)); ++ sess.key = (void *)"01234567890123456789012345678901234567890123456789"; ++ ++ for (i = 0, known_cipher_nids_amount = 0; ++ i < OSSL_NELEM(cipher_data); i++) { ++ ++ selected_ciphers[i] = 1; ++ /* ++ * Check that the cipher is usable ++ */ ++ sess.cipher = cipher_data[i].devcryptoid; ++ sess.keylen = cipher_data[i].keylen; ++ if (ioctl(cfd, CIOCGSESSION, &sess) < 0) { ++ cipher_driver_info[i].status = DEVCRYPTO_STATUS_NO_CIOCGSESSION; ++ continue; ++ } ++ ++ cipher_mode = cipher_data[i].flags & EVP_CIPH_MODE; ++ ++ if ((known_cipher_methods[i] = ++ EVP_CIPHER_meth_new(cipher_data[i].nid, ++ cipher_mode == EVP_CIPH_CTR_MODE ? 1 : ++ cipher_data[i].blocksize, ++ cipher_data[i].keylen)) == NULL ++ || !EVP_CIPHER_meth_set_iv_length(known_cipher_methods[i], ++ cipher_data[i].ivlen) ++ || !EVP_CIPHER_meth_set_flags(known_cipher_methods[i], ++ cipher_data[i].flags ++ | EVP_CIPH_CUSTOM_COPY ++ | EVP_CIPH_CTRL_INIT ++ | EVP_CIPH_FLAG_DEFAULT_ASN1) ++ || !EVP_CIPHER_meth_set_init(known_cipher_methods[i], cipher_init) ++ || !EVP_CIPHER_meth_set_do_cipher(known_cipher_methods[i], ++ cipher_mode == EVP_CIPH_CTR_MODE ? ++ ctr_do_cipher : ++ cipher_do_cipher) ++ || !EVP_CIPHER_meth_set_ctrl(known_cipher_methods[i], cipher_ctrl) ++ || !EVP_CIPHER_meth_set_cleanup(known_cipher_methods[i], ++ cipher_cleanup) ++ || !EVP_CIPHER_meth_set_impl_ctx_size(known_cipher_methods[i], ++ sizeof(struct cipher_ctx))) { ++ cipher_driver_info[i].status = DEVCRYPTO_STATUS_FAILURE; ++ EVP_CIPHER_meth_free(known_cipher_methods[i]); ++ known_cipher_methods[i] = NULL; ++ } else { ++ cipher_driver_info[i].status = DEVCRYPTO_STATUS_USABLE; ++#ifdef CIOCGSESSINFO ++ siop.ses = sess.ses; ++ if (ioctl(cfd, CIOCGSESSINFO, &siop) < 0) { ++ cipher_driver_info[i].accelerated = DEVCRYPTO_ACCELERATION_UNKNOWN; ++ } else { ++ cipher_driver_info[i].driver_name = ++ OPENSSL_strndup(siop.cipher_info.cra_driver_name, ++ CRYPTODEV_MAX_ALG_NAME); ++ if (!(siop.flags & SIOP_FLAG_KERNEL_DRIVER_ONLY)) ++ cipher_driver_info[i].accelerated = DEVCRYPTO_NOT_ACCELERATED; ++ else ++ cipher_driver_info[i].accelerated = DEVCRYPTO_ACCELERATED; ++ } ++#endif /* CIOCGSESSINFO */ ++ } ++ ioctl(cfd, CIOCFSESSION, &sess.ses); ++ if (devcrypto_test_cipher(i)) { ++ known_cipher_nids[known_cipher_nids_amount++] = ++ cipher_data[i].nid; ++ } ++ } ++} ++ ++static void rebuild_known_cipher_nids(ENGINE *e) ++{ ++ size_t i; ++ ++ for (i = 0, known_cipher_nids_amount = 0; i < OSSL_NELEM(cipher_data); i++) { ++ if (devcrypto_test_cipher(i)) ++ known_cipher_nids[known_cipher_nids_amount++] = cipher_data[i].nid; ++ } ++ ENGINE_unregister_ciphers(e); ++ ENGINE_register_ciphers(e); ++} ++ ++static const EVP_CIPHER *get_cipher_method(int nid) ++{ ++ size_t i = get_cipher_data_index(nid); ++ ++ if (i == (size_t)-1) ++ return NULL; ++ return known_cipher_methods[i]; ++} ++ ++static int get_cipher_nids(const int **nids) ++{ ++ *nids = known_cipher_nids; ++ return known_cipher_nids_amount; ++} ++ ++static void destroy_cipher_method(int nid) ++{ ++ size_t i = get_cipher_data_index(nid); ++ ++ EVP_CIPHER_meth_free(known_cipher_methods[i]); ++ known_cipher_methods[i] = NULL; ++} ++ ++static void destroy_all_cipher_methods(void) ++{ ++ size_t i; ++ ++ for (i = 0; i < OSSL_NELEM(cipher_data); i++) { ++ destroy_cipher_method(cipher_data[i].nid); ++ OPENSSL_free(cipher_driver_info[i].driver_name); ++ cipher_driver_info[i].driver_name = NULL; ++ } ++} ++ ++static int devcrypto_ciphers(ENGINE *e, const EVP_CIPHER **cipher, ++ const int **nids, int nid) ++{ ++ if (cipher == NULL) ++ return get_cipher_nids(nids); ++ ++ *cipher = get_cipher_method(nid); ++ ++ return *cipher != NULL; ++} ++ ++static void devcrypto_select_all_ciphers(int *cipher_list) ++{ ++ size_t i; ++ ++ for (i = 0; i < OSSL_NELEM(cipher_data); i++) ++ cipher_list[i] = 1; ++} ++ ++static int cryptodev_select_cipher_cb(const char *str, int len, void *usr) ++{ ++ int *cipher_list = (int *)usr; ++ char *name; ++ const EVP_CIPHER *EVP; ++ size_t i; ++ ++ if (len == 0) ++ return 1; ++ if (usr == NULL || (name = OPENSSL_strndup(str, len)) == NULL) ++ return 0; ++ EVP = EVP_get_cipherbyname(name); ++ if (EVP == NULL) ++ fprintf(stderr, "devcrypto: unknown cipher %s\n", name); ++ else if ((i = find_cipher_data_index(EVP_CIPHER_nid(EVP))) != (size_t)-1) ++ cipher_list[i] = 1; ++ else ++ fprintf(stderr, "devcrypto: cipher %s not available\n", name); ++ OPENSSL_free(name); ++ return 1; ++} ++ ++static void dump_cipher_info(void) ++{ ++ size_t i; ++ const char *name; ++ ++ fprintf (stderr, "Information about ciphers supported by the /dev/crypto" ++ " engine:\n"); ++#ifndef CIOCGSESSINFO ++ fprintf(stderr, "CIOCGSESSINFO (session info call) unavailable\n"); ++#endif ++ for (i = 0; i < OSSL_NELEM(cipher_data); i++) { ++ name = OBJ_nid2sn(cipher_data[i].nid); ++ fprintf (stderr, "Cipher %s, NID=%d, /dev/crypto info: id=%d, ", ++ name ? name : "unknown", cipher_data[i].nid, ++ cipher_data[i].devcryptoid); ++ if (cipher_driver_info[i].status == DEVCRYPTO_STATUS_NO_CIOCGSESSION ) { ++ fprintf (stderr, "CIOCGSESSION (session open call) failed\n"); ++ continue; ++ } ++ fprintf (stderr, "driver=%s ", cipher_driver_info[i].driver_name ? ++ cipher_driver_info[i].driver_name : "unknown"); ++ if (cipher_driver_info[i].accelerated == DEVCRYPTO_ACCELERATED) ++ fprintf(stderr, "(hw accelerated)"); ++ else if (cipher_driver_info[i].accelerated == DEVCRYPTO_NOT_ACCELERATED) ++ fprintf(stderr, "(software)"); ++ else ++ fprintf(stderr, "(acceleration status unknown)"); ++ if (cipher_driver_info[i].status == DEVCRYPTO_STATUS_FAILURE) ++ fprintf (stderr, ". Cipher setup failed"); ++ fprintf(stderr, "\n"); ++ } ++ fprintf(stderr, "\n"); ++} ++ ++/* ++ * We only support digests if the cryptodev implementation supports multiple ++ * data updates and session copying. Otherwise, we would be forced to maintain ++ * a cache, which is perilous if there's a lot of data coming in (if someone ++ * wants to checksum an OpenSSL tarball, for example). ++ */ ++#if defined(CIOCCPHASH) && defined(COP_FLAG_UPDATE) && defined(COP_FLAG_FINAL) ++#define IMPLEMENT_DIGEST ++ ++/****************************************************************************** ++ * ++ * Digests ++ * ++ * Because they all do the same basic operation, we have only one set of ++ * method functions for them all to share, and a mapping table between ++ * NIDs and cryptodev IDs, with all the necessary size data. ++ * ++ *****/ ++ ++struct digest_ctx { ++ struct session_op sess; ++ /* This signals that the init function was called, not that it succeeded. */ ++ int init_called; ++ unsigned char digest_res[HASH_MAX_LEN]; ++}; ++ ++static const struct digest_data_st { ++ int nid; ++ int blocksize; ++ int digestlen; ++ int devcryptoid; ++} digest_data[] = { ++#ifndef OPENSSL_NO_MD5 ++ { NID_md5, /* MD5_CBLOCK */ 64, 16, CRYPTO_MD5 }, ++#endif ++ { NID_sha1, SHA_CBLOCK, 20, CRYPTO_SHA1 }, ++#ifndef OPENSSL_NO_RMD160 ++# if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_RIPEMD160) ++ { NID_ripemd160, /* RIPEMD160_CBLOCK */ 64, 20, CRYPTO_RIPEMD160 }, ++# endif ++#endif ++#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_224) ++ { NID_sha224, SHA256_CBLOCK, 224 / 8, CRYPTO_SHA2_224 }, ++#endif ++#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_256) ++ { NID_sha256, SHA256_CBLOCK, 256 / 8, CRYPTO_SHA2_256 }, ++#endif ++#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_384) ++ { NID_sha384, SHA512_CBLOCK, 384 / 8, CRYPTO_SHA2_384 }, ++#endif ++#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_512) ++ { NID_sha512, SHA512_CBLOCK, 512 / 8, CRYPTO_SHA2_512 }, ++#endif ++}; ++ ++static size_t find_digest_data_index(int nid) ++{ ++ size_t i; ++ ++ for (i = 0; i < OSSL_NELEM(digest_data); i++) ++ if (nid == digest_data[i].nid) ++ return i; ++ return (size_t)-1; ++} ++ ++static size_t get_digest_data_index(int nid) ++{ ++ size_t i = find_digest_data_index(nid); ++ ++ if (i != (size_t)-1) ++ return i; ++ ++ /* ++ * Code further down must make sure that only NIDs in the table above ++ * are used. If any other NID reaches this function, there's a grave ++ * coding error further down. ++ */ ++ assert("Code that never should be reached" == NULL); ++ return -1; ++} ++ ++static const struct digest_data_st *get_digest_data(int nid) ++{ ++ return &digest_data[get_digest_data_index(nid)]; ++} ++ ++/* ++ * Following are the five necessary functions to map OpenSSL functionality ++ * with cryptodev: init, update, final, cleanup, and copy. ++ */ ++ ++static int digest_init(EVP_MD_CTX *ctx) ++{ ++ struct digest_ctx *digest_ctx = ++ (struct digest_ctx *)EVP_MD_CTX_md_data(ctx); ++ const struct digest_data_st *digest_d = ++ get_digest_data(EVP_MD_CTX_type(ctx)); ++ ++ digest_ctx->init_called = 1; ++ ++ memset(&digest_ctx->sess, 0, sizeof(digest_ctx->sess)); ++ digest_ctx->sess.mac = digest_d->devcryptoid; ++ if (ioctl(cfd, CIOCGSESSION, &digest_ctx->sess) < 0) { ++ SYSerr(SYS_F_IOCTL, errno); ++ return 0; ++ } ++ return 1; ++} ++ ++static int digest_op(struct digest_ctx *ctx, const void *src, size_t srclen, ++ void *res, unsigned int flags) ++{ ++ struct crypt_op cryp; ++ ++ memset(&cryp, 0, sizeof(cryp)); ++ cryp.ses = ctx->sess.ses; ++ cryp.len = srclen; ++ cryp.src = (void *)src; ++ cryp.dst = NULL; ++ cryp.mac = res; ++ cryp.flags = flags; ++ return ioctl(cfd, CIOCCRYPT, &cryp); ++} ++ ++static int digest_update(EVP_MD_CTX *ctx, const void *data, size_t count) ++{ ++ struct digest_ctx *digest_ctx = ++ (struct digest_ctx *)EVP_MD_CTX_md_data(ctx); ++ ++ if (count == 0) ++ return 1; ++ ++ if (digest_ctx == NULL) ++ return 0; ++ ++ if (EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_ONESHOT)) { ++ if (digest_op(digest_ctx, data, count, digest_ctx->digest_res, 0) >= 0) ++ return 1; ++ } else if (digest_op(digest_ctx, data, count, NULL, COP_FLAG_UPDATE) >= 0) { ++ return 1; ++ } ++ ++ SYSerr(SYS_F_IOCTL, errno); ++ return 0; ++} ++ ++static int digest_final(EVP_MD_CTX *ctx, unsigned char *md) ++{ ++ struct digest_ctx *digest_ctx = ++ (struct digest_ctx *)EVP_MD_CTX_md_data(ctx); ++ ++ if (md == NULL || digest_ctx == NULL) ++ return 0; ++ ++ if (EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_ONESHOT)) { ++ memcpy(md, digest_ctx->digest_res, EVP_MD_CTX_size(ctx)); ++ } else if (digest_op(digest_ctx, NULL, 0, md, COP_FLAG_FINAL) < 0) { ++ SYSerr(SYS_F_IOCTL, errno); ++ return 0; ++ } ++ ++ return 1; ++} ++ ++static int digest_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from) ++{ ++ struct digest_ctx *digest_from = ++ (struct digest_ctx *)EVP_MD_CTX_md_data(from); ++ struct digest_ctx *digest_to = ++ (struct digest_ctx *)EVP_MD_CTX_md_data(to); ++ struct cphash_op cphash; ++ ++ if (digest_from == NULL || digest_from->init_called != 1) ++ return 1; ++ ++ if (!digest_init(to)) { ++ SYSerr(SYS_F_IOCTL, errno); ++ return 0; ++ } ++ ++ cphash.src_ses = digest_from->sess.ses; ++ cphash.dst_ses = digest_to->sess.ses; ++ if (ioctl(cfd, CIOCCPHASH, &cphash) < 0) { ++ SYSerr(SYS_F_IOCTL, errno); ++ return 0; ++ } ++ return 1; ++} ++ ++static int digest_cleanup(EVP_MD_CTX *ctx) ++{ ++ struct digest_ctx *digest_ctx = ++ (struct digest_ctx *)EVP_MD_CTX_md_data(ctx); ++ ++ if (digest_ctx == NULL) ++ return 1; ++ ++ return clean_devcrypto_session(&digest_ctx->sess); ++} ++ ++/* ++ * Keep tables of known nids, associated methods, selected digests, and ++ * driver info. ++ * Note that known_digest_nids[] isn't necessarily indexed the same way as ++ * digest_data[] above, which the other tables are. ++ */ ++static int known_digest_nids[OSSL_NELEM(digest_data)]; ++static int known_digest_nids_amount = -1; /* -1 indicates not yet initialised */ ++static EVP_MD *known_digest_methods[OSSL_NELEM(digest_data)] = { NULL, }; ++static int selected_digests[OSSL_NELEM(digest_data)]; ++static struct driver_info_st digest_driver_info[OSSL_NELEM(digest_data)]; ++ ++static int devcrypto_test_digest(size_t digest_data_index) ++{ ++ return (digest_driver_info[digest_data_index].status == DEVCRYPTO_STATUS_USABLE ++ && selected_digests[digest_data_index] == 1 ++ && (digest_driver_info[digest_data_index].accelerated ++ == DEVCRYPTO_ACCELERATED ++ || use_softdrivers == DEVCRYPTO_USE_SOFTWARE ++ || (digest_driver_info[digest_data_index].accelerated ++ != DEVCRYPTO_NOT_ACCELERATED ++ && use_softdrivers == DEVCRYPTO_REJECT_SOFTWARE))); ++} ++ ++static void rebuild_known_digest_nids(ENGINE *e) ++{ ++ size_t i; ++ ++ for (i = 0, known_digest_nids_amount = 0; i < OSSL_NELEM(digest_data); i++) { ++ if (devcrypto_test_digest(i)) ++ known_digest_nids[known_digest_nids_amount++] = digest_data[i].nid; ++ } ++ ENGINE_unregister_digests(e); ++ ENGINE_register_digests(e); ++} ++ ++static void prepare_digest_methods(void) ++{ ++ size_t i; ++ struct session_op sess1, sess2; ++#ifdef CIOCGSESSINFO ++ struct session_info_op siop; ++#endif ++ struct cphash_op cphash; ++ ++ memset(&digest_driver_info, 0, sizeof(digest_driver_info)); ++ ++ memset(&sess1, 0, sizeof(sess1)); ++ memset(&sess2, 0, sizeof(sess2)); ++ ++ for (i = 0, known_digest_nids_amount = 0; i < OSSL_NELEM(digest_data); ++ i++) { ++ ++ selected_digests[i] = 1; ++ ++ /* ++ * Check that the digest is usable ++ */ ++ sess1.mac = digest_data[i].devcryptoid; ++ sess2.ses = 0; ++ if (ioctl(cfd, CIOCGSESSION, &sess1) < 0) { ++ digest_driver_info[i].status = DEVCRYPTO_STATUS_NO_CIOCGSESSION; ++ goto finish; ++ } ++ ++#ifdef CIOCGSESSINFO ++ /* gather hardware acceleration info from the driver */ ++ siop.ses = sess1.ses; ++ if (ioctl(cfd, CIOCGSESSINFO, &siop) < 0) { ++ digest_driver_info[i].accelerated = DEVCRYPTO_ACCELERATION_UNKNOWN; ++ } else { ++ digest_driver_info[i].driver_name = ++ OPENSSL_strndup(siop.hash_info.cra_driver_name, ++ CRYPTODEV_MAX_ALG_NAME); ++ if (siop.flags & SIOP_FLAG_KERNEL_DRIVER_ONLY) ++ digest_driver_info[i].accelerated = DEVCRYPTO_ACCELERATED; ++ else ++ digest_driver_info[i].accelerated = DEVCRYPTO_NOT_ACCELERATED; ++ } ++#endif ++ ++ /* digest must be capable of hash state copy */ ++ sess2.mac = sess1.mac; ++ if (ioctl(cfd, CIOCGSESSION, &sess2) < 0) { ++ digest_driver_info[i].status = DEVCRYPTO_STATUS_FAILURE; ++ goto finish; ++ } ++ cphash.src_ses = sess1.ses; ++ cphash.dst_ses = sess2.ses; ++ if (ioctl(cfd, CIOCCPHASH, &cphash) < 0) { ++ digest_driver_info[i].status = DEVCRYPTO_STATUS_NO_CIOCCPHASH; ++ goto finish; ++ } ++ if ((known_digest_methods[i] = EVP_MD_meth_new(digest_data[i].nid, ++ NID_undef)) == NULL ++ || !EVP_MD_meth_set_input_blocksize(known_digest_methods[i], ++ digest_data[i].blocksize) ++ || !EVP_MD_meth_set_result_size(known_digest_methods[i], ++ digest_data[i].digestlen) ++ || !EVP_MD_meth_set_init(known_digest_methods[i], digest_init) ++ || !EVP_MD_meth_set_update(known_digest_methods[i], digest_update) ++ || !EVP_MD_meth_set_final(known_digest_methods[i], digest_final) ++ || !EVP_MD_meth_set_copy(known_digest_methods[i], digest_copy) ++ || !EVP_MD_meth_set_cleanup(known_digest_methods[i], digest_cleanup) ++ || !EVP_MD_meth_set_app_datasize(known_digest_methods[i], ++ sizeof(struct digest_ctx))) { ++ digest_driver_info[i].status = DEVCRYPTO_STATUS_FAILURE; ++ EVP_MD_meth_free(known_digest_methods[i]); ++ known_digest_methods[i] = NULL; ++ goto finish; ++ } ++ digest_driver_info[i].status = DEVCRYPTO_STATUS_USABLE; ++finish: ++ ioctl(cfd, CIOCFSESSION, &sess1.ses); ++ if (sess2.ses != 0) ++ ioctl(cfd, CIOCFSESSION, &sess2.ses); ++ if (devcrypto_test_digest(i)) ++ known_digest_nids[known_digest_nids_amount++] = digest_data[i].nid; ++ } ++} ++ ++static const EVP_MD *get_digest_method(int nid) ++{ ++ size_t i = get_digest_data_index(nid); ++ ++ if (i == (size_t)-1) ++ return NULL; ++ return known_digest_methods[i]; ++} ++ ++static int get_digest_nids(const int **nids) ++{ ++ *nids = known_digest_nids; ++ return known_digest_nids_amount; ++} ++ ++static void destroy_digest_method(int nid) ++{ ++ size_t i = get_digest_data_index(nid); ++ ++ EVP_MD_meth_free(known_digest_methods[i]); ++ known_digest_methods[i] = NULL; ++} ++ ++static void destroy_all_digest_methods(void) ++{ ++ size_t i; ++ ++ for (i = 0; i < OSSL_NELEM(digest_data); i++) { ++ destroy_digest_method(digest_data[i].nid); ++ OPENSSL_free(digest_driver_info[i].driver_name); ++ digest_driver_info[i].driver_name = NULL; ++ } ++} ++ ++static int devcrypto_digests(ENGINE *e, const EVP_MD **digest, ++ const int **nids, int nid) ++{ ++ if (digest == NULL) ++ return get_digest_nids(nids); ++ ++ *digest = get_digest_method(nid); ++ ++ return *digest != NULL; ++} ++ ++static void devcrypto_select_all_digests(int *digest_list) ++{ ++ size_t i; ++ ++ for (i = 0; i < OSSL_NELEM(digest_data); i++) ++ digest_list[i] = 1; ++} ++ ++static int cryptodev_select_digest_cb(const char *str, int len, void *usr) ++{ ++ int *digest_list = (int *)usr; ++ char *name; ++ const EVP_MD *EVP; ++ size_t i; ++ ++ if (len == 0) ++ return 1; ++ if (usr == NULL || (name = OPENSSL_strndup(str, len)) == NULL) ++ return 0; ++ EVP = EVP_get_digestbyname(name); ++ if (EVP == NULL) ++ fprintf(stderr, "devcrypto: unknown digest %s\n", name); ++ else if ((i = find_digest_data_index(EVP_MD_type(EVP))) != (size_t)-1) ++ digest_list[i] = 1; ++ else ++ fprintf(stderr, "devcrypto: digest %s not available\n", name); ++ OPENSSL_free(name); ++ return 1; ++} ++ ++static void dump_digest_info(void) ++{ ++ size_t i; ++ const char *name; ++ ++ fprintf (stderr, "Information about digests supported by the /dev/crypto" ++ " engine:\n"); ++#ifndef CIOCGSESSINFO ++ fprintf(stderr, "CIOCGSESSINFO (session info call) unavailable\n"); ++#endif ++ ++ for (i = 0; i < OSSL_NELEM(digest_data); i++) { ++ name = OBJ_nid2sn(digest_data[i].nid); ++ fprintf (stderr, "Digest %s, NID=%d, /dev/crypto info: id=%d, driver=%s", ++ name ? name : "unknown", digest_data[i].nid, ++ digest_data[i].devcryptoid, ++ digest_driver_info[i].driver_name ? digest_driver_info[i].driver_name : "unknown"); ++ if (digest_driver_info[i].status == DEVCRYPTO_STATUS_NO_CIOCGSESSION) { ++ fprintf (stderr, ". CIOCGSESSION (session open) failed\n"); ++ continue; ++ } ++ if (digest_driver_info[i].accelerated == DEVCRYPTO_ACCELERATED) ++ fprintf(stderr, " (hw accelerated)"); ++ else if (digest_driver_info[i].accelerated == DEVCRYPTO_NOT_ACCELERATED) ++ fprintf(stderr, " (software)"); ++ else ++ fprintf(stderr, " (acceleration status unknown)"); ++ if (cipher_driver_info[i].status == DEVCRYPTO_STATUS_FAILURE) ++ fprintf (stderr, ". Cipher setup failed\n"); ++ else if (digest_driver_info[i].status == DEVCRYPTO_STATUS_NO_CIOCCPHASH) ++ fprintf(stderr, ", CIOCCPHASH failed\n"); ++ else ++ fprintf(stderr, ", CIOCCPHASH capable\n"); ++ } ++ fprintf(stderr, "\n"); ++} ++ ++#endif ++ ++/****************************************************************************** ++ * ++ * CONTROL COMMANDS ++ * ++ *****/ ++ ++#define DEVCRYPTO_CMD_USE_SOFTDRIVERS ENGINE_CMD_BASE ++#define DEVCRYPTO_CMD_CIPHERS (ENGINE_CMD_BASE + 1) ++#define DEVCRYPTO_CMD_DIGESTS (ENGINE_CMD_BASE + 2) ++#define DEVCRYPTO_CMD_DUMP_INFO (ENGINE_CMD_BASE + 3) ++ ++/* Helper macros for CPP string composition */ ++#ifndef OPENSSL_MSTR ++# define OPENSSL_MSTR_HELPER(x) #x ++# define OPENSSL_MSTR(x) OPENSSL_MSTR_HELPER(x) ++#endif ++ ++static const ENGINE_CMD_DEFN devcrypto_cmds[] = { ++#ifdef CIOCGSESSINFO ++ {DEVCRYPTO_CMD_USE_SOFTDRIVERS, ++ "USE_SOFTDRIVERS", ++ "specifies whether to use software (not accelerated) drivers (" ++ OPENSSL_MSTR(DEVCRYPTO_REQUIRE_ACCELERATED) "=use only accelerated drivers, " ++ OPENSSL_MSTR(DEVCRYPTO_USE_SOFTWARE) "=allow all drivers, " ++ OPENSSL_MSTR(DEVCRYPTO_REJECT_SOFTWARE) ++ "=use if acceleration can't be determined) [default=" ++ OPENSSL_MSTR(DEVCRYPTO_DEFAULT_USE_SOFTDRIVERS) "]", ++ ENGINE_CMD_FLAG_NUMERIC}, ++#endif ++ ++ {DEVCRYPTO_CMD_CIPHERS, ++ "CIPHERS", ++ "either ALL, NONE, or a comma-separated list of ciphers to enable [default=ALL]", ++ ENGINE_CMD_FLAG_STRING}, ++ ++#ifdef IMPLEMENT_DIGEST ++ {DEVCRYPTO_CMD_DIGESTS, ++ "DIGESTS", ++ "either ALL, NONE, or a comma-separated list of digests to enable [default=ALL]", ++ ENGINE_CMD_FLAG_STRING}, ++#endif ++ ++ {DEVCRYPTO_CMD_DUMP_INFO, ++ "DUMP_INFO", ++ "dump info about each algorithm to stderr; use 'openssl engine -pre DUMP_INFO devcrypto'", ++ ENGINE_CMD_FLAG_NO_INPUT}, ++ ++ {0, NULL, NULL, 0} ++}; ++ ++static int devcrypto_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void)) ++{ ++ int *new_list; ++ switch (cmd) { ++#ifdef CIOCGSESSINFO ++ case DEVCRYPTO_CMD_USE_SOFTDRIVERS: ++ switch (i) { ++ case DEVCRYPTO_REQUIRE_ACCELERATED: ++ case DEVCRYPTO_USE_SOFTWARE: ++ case DEVCRYPTO_REJECT_SOFTWARE: ++ break; ++ default: ++ fprintf(stderr, "devcrypto: invalid value (%ld) for USE_SOFTDRIVERS\n", i); ++ return 0; ++ } ++ if (use_softdrivers == i) ++ return 1; ++ use_softdrivers = i; ++#ifdef IMPLEMENT_DIGEST ++ rebuild_known_digest_nids(e); ++#endif ++ rebuild_known_cipher_nids(e); ++ return 1; ++#endif /* CIOCGSESSINFO */ ++ ++ case DEVCRYPTO_CMD_CIPHERS: ++ if (p == NULL) ++ return 1; ++ if (strcasecmp((const char *)p, "ALL") == 0) { ++ devcrypto_select_all_ciphers(selected_ciphers); ++ } else if (strcasecmp((const char*)p, "NONE") == 0) { ++ memset(selected_ciphers, 0, sizeof(selected_ciphers)); ++ } else { ++ new_list=OPENSSL_zalloc(sizeof(selected_ciphers)); ++ if (!CONF_parse_list(p, ',', 1, cryptodev_select_cipher_cb, new_list)) { ++ OPENSSL_free(new_list); ++ return 0; ++ } ++ memcpy(selected_ciphers, new_list, sizeof(selected_ciphers)); ++ OPENSSL_free(new_list); ++ } ++ rebuild_known_cipher_nids(e); ++ return 1; ++ ++#ifdef IMPLEMENT_DIGEST ++ case DEVCRYPTO_CMD_DIGESTS: ++ if (p == NULL) ++ return 1; ++ if (strcasecmp((const char *)p, "ALL") == 0) { ++ devcrypto_select_all_digests(selected_digests); ++ } else if (strcasecmp((const char*)p, "NONE") == 0) { ++ memset(selected_digests, 0, sizeof(selected_digests)); ++ } else { ++ new_list=OPENSSL_zalloc(sizeof(selected_digests)); ++ if (!CONF_parse_list(p, ',', 1, cryptodev_select_digest_cb, new_list)) { ++ OPENSSL_free(new_list); ++ return 0; ++ } ++ memcpy(selected_digests, new_list, sizeof(selected_digests)); ++ OPENSSL_free(new_list); ++ } ++ rebuild_known_digest_nids(e); ++ return 1; ++#endif /* IMPLEMENT_DIGEST */ ++ ++ case DEVCRYPTO_CMD_DUMP_INFO: ++ dump_cipher_info(); ++#ifdef IMPLEMENT_DIGEST ++ dump_digest_info(); ++#endif ++ return 1; ++ ++ default: ++ break; ++ } ++ return 0; ++} ++ ++/****************************************************************************** ++ * ++ * LOAD / UNLOAD ++ * ++ *****/ ++ ++/* ++ * Opens /dev/crypto ++ */ ++static int open_devcrypto(void) ++{ ++ if (cfd >= 0) ++ return 1; ++ ++ if ((cfd = open("/dev/crypto", O_RDWR, 0)) < 0) { ++#ifndef ENGINE_DEVCRYPTO_DEBUG ++ if (errno != ENOENT) ++#endif ++ fprintf(stderr, "Could not open /dev/crypto: %s\n", strerror(errno)); ++ return 0; ++ } ++ + return 1; +} + @@ -237,20 +2576,17 @@ index 0d420e50aa..3fcd81de7a 100644 + if (ret != 0) { + fprintf(stderr, "Error closing /dev/crypto: %s\n", strerror(errno)); + return 0; - } ++ } + return 1; +} - -- prepare_cipher_methods(); ++ +static int devcrypto_unload(ENGINE *e) +{ + destroy_all_cipher_methods(); - #ifdef IMPLEMENT_DIGEST -- prepare_digest_methods(); ++#ifdef IMPLEMENT_DIGEST + destroy_all_digest_methods(); - #endif - -- if (!ENGINE_set_id(e, "devcrypto") ++#endif ++ + close_devcrypto(); + + return 1; @@ -259,13 +2595,12 @@ index 0d420e50aa..3fcd81de7a 100644 +static int bind_devcrypto(ENGINE *e) { + + if (!ENGINE_set_id(e, engine_devcrypto_id) - || !ENGINE_set_name(e, "/dev/crypto engine") ++ || !ENGINE_set_name(e, "/dev/crypto engine") + || !ENGINE_set_destroy_function(e, devcrypto_unload) - || !ENGINE_set_cmd_defns(e, devcrypto_cmds) -- || !ENGINE_set_ctrl_function(e, devcrypto_ctrl) ++ || !ENGINE_set_cmd_defns(e, devcrypto_cmds) + || !ENGINE_set_ctrl_function(e, devcrypto_ctrl)) + return 0; - ++ + prepare_cipher_methods(); +#ifdef IMPLEMENT_DIGEST + prepare_digest_methods(); @@ -275,34 +2610,40 @@ index 0d420e50aa..3fcd81de7a 100644 +#ifdef IMPLEMENT_DIGEST + && ENGINE_set_digests(e, devcrypto_digests) +#endif - /* - * Asymmetric ciphers aren't well supported with /dev/crypto. Among the BSD - * implementations, it seems to only exist in FreeBSD, and regarding the -@@ -1237,23 +1254,36 @@ void engine_load_devcrypto_int() - */ - #if 0 - # ifndef OPENSSL_NO_RSA -- || !ENGINE_set_RSA(e, devcrypto_rsa) ++/* ++ * Asymmetric ciphers aren't well supported with /dev/crypto. Among the BSD ++ * implementations, it seems to only exist in FreeBSD, and regarding the ++ * parameters in its crypt_kop, the manual crypto(4) has this to say: ++ * ++ * The semantics of these arguments are currently undocumented. ++ * ++ * Reading through the FreeBSD source code doesn't give much more than ++ * their CRK_MOD_EXP implementation for ubsec. ++ * ++ * It doesn't look much better with cryptodev-linux. They have the crypt_kop ++ * structure as well as the command (CRK_*) in cryptodev.h, but no support ++ * seems to be implemented at all for the moment. ++ * ++ * At the time of writing, it seems impossible to write proper support for ++ * FreeBSD's asym features without some very deep knowledge and access to ++ * specific kernel modules. ++ * ++ * /Richard Levitte, 2017-05-11 ++ */ ++#if 0 ++# ifndef OPENSSL_NO_RSA + && ENGINE_set_RSA(e, devcrypto_rsa) - # endif - # ifndef OPENSSL_NO_DSA -- || !ENGINE_set_DSA(e, devcrypto_dsa) ++# endif ++# ifndef OPENSSL_NO_DSA + && ENGINE_set_DSA(e, devcrypto_dsa) - # endif - # ifndef OPENSSL_NO_DH -- || !ENGINE_set_DH(e, devcrypto_dh) ++# endif ++# ifndef OPENSSL_NO_DH + && ENGINE_set_DH(e, devcrypto_dh) - # endif - # ifndef OPENSSL_NO_EC -- || !ENGINE_set_EC(e, devcrypto_ec) ++# endif ++# ifndef OPENSSL_NO_EC + && ENGINE_set_EC(e, devcrypto_ec) - # endif - #endif -- || !ENGINE_set_ciphers(e, devcrypto_ciphers) --#ifdef IMPLEMENT_DIGEST -- || !ENGINE_set_digests(e, devcrypto_digests) --#endif -- ) { ++# endif ++#endif + ); +} + @@ -321,13 +2662,14 @@ index 0d420e50aa..3fcd81de7a 100644 + if ((e = ENGINE_new()) == NULL + || !bind_devcrypto(e)) { + close_devcrypto(); - ENGINE_free(e); - return; - } -@@ -1262,3 +1292,22 @@ void engine_load_devcrypto_int() - ENGINE_free(e); /* Loose our local reference */ - ERR_clear_error(); - } ++ ENGINE_free(e); ++ return; ++ } ++ ++ ENGINE_add(e); ++ ENGINE_free(e); /* Loose our local reference */ ++ ERR_clear_error(); ++} + +#else + diff --git a/package/libs/openssl/patches/500-e_devcrypto-default-to-not-use-digests-in-engine.patch b/package/libs/openssl/patches/500-e_devcrypto-default-to-not-use-digests-in-engine.patch index 1f1cd7a582..df5c16d8d2 100644 --- a/package/libs/openssl/patches/500-e_devcrypto-default-to-not-use-digests-in-engine.patch +++ b/package/libs/openssl/patches/500-e_devcrypto-default-to-not-use-digests-in-engine.patch @@ -19,8 +19,6 @@ turn them on if it is safe and fast enough. Signed-off-by: Eneas U de Queiroz -diff --git a/engines/e_devcrypto.c b/engines/e_devcrypto.c -index 3fcd81de7a..d25230d366 100644 --- a/engines/e_devcrypto.c +++ b/engines/e_devcrypto.c @@ -852,7 +852,7 @@ static void prepare_digest_methods(void) @@ -32,7 +30,7 @@ index 3fcd81de7a..d25230d366 100644 /* * Check that the digest is usable -@@ -1072,7 +1072,7 @@ static const ENGINE_CMD_DEFN devcrypto_cmds[] = { +@@ -1072,7 +1072,7 @@ static const ENGINE_CMD_DEFN devcrypto_c #ifdef IMPLEMENT_DIGEST {DEVCRYPTO_CMD_DIGESTS, "DIGESTS", diff --git a/package/libs/openssl/patches/510-e_devcrypto-ignore-error-when-closing-session.patch b/package/libs/openssl/patches/510-e_devcrypto-ignore-error-when-closing-session.patch index bc514b88c9..87792cf9d0 100644 --- a/package/libs/openssl/patches/510-e_devcrypto-ignore-error-when-closing-session.patch +++ b/package/libs/openssl/patches/510-e_devcrypto-ignore-error-when-closing-session.patch @@ -8,11 +8,9 @@ session. It may have been closed by another process after a fork. Signed-off-by: Eneas U de Queiroz -diff --git a/engines/e_devcrypto.c b/engines/e_devcrypto.c -index d25230d366..f4570f1666 100644 --- a/engines/e_devcrypto.c +++ b/engines/e_devcrypto.c -@@ -195,9 +195,8 @@ static int cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, +@@ -195,9 +195,8 @@ static int cipher_init(EVP_CIPHER_CTX *c get_cipher_data(EVP_CIPHER_CTX_nid(ctx)); /* cleanup a previous session */ From bbb9c1c2bebb98793d7ccf64da19e34ff08c8706 Mon Sep 17 00:00:00 2001 From: Kevin Darbyshire-Bryant Date: Fri, 26 Mar 2021 09:12:12 +0000 Subject: [PATCH 31/31] Revert "openssl: refresh patches" This reverts commit e27ef2da0d513494c3e9926ce8d44b63e4236a32. Signed-off-by: Kevin Darbyshire-Bryant --- .../patches/100-Configure-afalg-support.patch | 4 +- .../openssl/patches/110-openwrt_targets.patch | 3 + .../120-strip-cflags-from-binary.patch | 4 +- .../patches/130-dont-build-tests-fuzz.patch | 4 +- .../patches/140-allow-prefer-chacha20.patch | 8 +- ...o-save-ioctl-if-EVP_MD_.FLAG_ONESHOT.patch | 6 +- ..._devcrypto-add-configuration-options.patch | 21 +- ...ypto-add-command-to-dump-driver-info.patch | 16 +- ...o-make-the-dev-crypto-engine-dynamic.patch | 2606 +---------------- ...default-to-not-use-digests-in-engine.patch | 4 +- ...to-ignore-error-when-closing-session.patch | 4 +- 11 files changed, 181 insertions(+), 2499 deletions(-) diff --git a/package/libs/openssl/patches/100-Configure-afalg-support.patch b/package/libs/openssl/patches/100-Configure-afalg-support.patch index f62c35879e..98944103b5 100644 --- a/package/libs/openssl/patches/100-Configure-afalg-support.patch +++ b/package/libs/openssl/patches/100-Configure-afalg-support.patch @@ -8,9 +8,11 @@ version to disable building the AFALG engine on openwrt targets. Signed-off-by: Eneas U de Queiroz +diff --git a/Configure b/Configure +index 5a699836f3..74d057c219 100755 --- a/Configure +++ b/Configure -@@ -1545,7 +1545,9 @@ unless ($disabled{"crypto-mdebug-backtra +@@ -1545,7 +1545,9 @@ unless ($disabled{"crypto-mdebug-backtrace"}) unless ($disabled{afalgeng}) { $config{afalgeng}=""; diff --git a/package/libs/openssl/patches/110-openwrt_targets.patch b/package/libs/openssl/patches/110-openwrt_targets.patch index b2786e8fee..d0530b4661 100644 --- a/package/libs/openssl/patches/110-openwrt_targets.patch +++ b/package/libs/openssl/patches/110-openwrt_targets.patch @@ -7,6 +7,9 @@ Targets are named: linux-$(CONFIG_ARCH)-openwrt Signed-off-by: Eneas U de Queiroz +diff --git a/Configurations/25-openwrt.conf b/Configurations/25-openwrt.conf +new file mode 100644 +index 0000000000..86a86d31e4 --- /dev/null +++ b/Configurations/25-openwrt.conf @@ -0,0 +1,48 @@ diff --git a/package/libs/openssl/patches/120-strip-cflags-from-binary.patch b/package/libs/openssl/patches/120-strip-cflags-from-binary.patch index 4a7dce366b..7faec9ab88 100644 --- a/package/libs/openssl/patches/120-strip-cflags-from-binary.patch +++ b/package/libs/openssl/patches/120-strip-cflags-from-binary.patch @@ -8,9 +8,11 @@ OpenSSL_version(OPENSSL_CFLAGS), or running openssl version -a Signed-off-by: Eneas U de Queiroz +diff --git a/crypto/build.info b/crypto/build.info +index 2c619c62e8..893128345a 100644 --- a/crypto/build.info +++ b/crypto/build.info -@@ -10,7 +10,7 @@ EXTRA= ../ms/uplink-x86.pl ../ms/uplink +@@ -10,7 +10,7 @@ EXTRA= ../ms/uplink-x86.pl ../ms/uplink.c ../ms/applink.c \ ppccpuid.pl pariscid.pl alphacpuid.pl arm64cpuid.pl armv4cpuid.pl DEPEND[cversion.o]=buildinf.h diff --git a/package/libs/openssl/patches/130-dont-build-tests-fuzz.patch b/package/libs/openssl/patches/130-dont-build-tests-fuzz.patch index 1117f7152f..7f33cb9dae 100644 --- a/package/libs/openssl/patches/130-dont-build-tests-fuzz.patch +++ b/package/libs/openssl/patches/130-dont-build-tests-fuzz.patch @@ -7,9 +7,11 @@ This shortens build time. Signed-off-by: Eneas U de Queiroz +diff --git a/Configure b/Configure +index 74d057c219..5813e9f8fe 100755 --- a/Configure +++ b/Configure -@@ -318,7 +318,7 @@ my $auto_threads=1; # enable threads +@@ -318,7 +318,7 @@ my $auto_threads=1; # enable threads automatically? true by default my $default_ranlib; # Top level directories to build diff --git a/package/libs/openssl/patches/140-allow-prefer-chacha20.patch b/package/libs/openssl/patches/140-allow-prefer-chacha20.patch index 71c7c72881..b293db28f7 100644 --- a/package/libs/openssl/patches/140-allow-prefer-chacha20.patch +++ b/package/libs/openssl/patches/140-allow-prefer-chacha20.patch @@ -14,6 +14,8 @@ when the client has it on top of its ciphersuite preference. Signed-off-by: Eneas U de Queiroz +diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h +index 6724ccf2d2..96d959427e 100644 --- a/include/openssl/ssl.h +++ b/include/openssl/ssl.h @@ -173,9 +173,15 @@ extern "C" { @@ -35,9 +37,11 @@ Signed-off-by: Eneas U de Queiroz # else # define TLS_DEFAULT_CIPHERSUITES "TLS_AES_256_GCM_SHA384:" \ "TLS_AES_128_GCM_SHA256" +diff --git a/ssl/ssl_ciph.c b/ssl/ssl_ciph.c +index 27a1b2ec68..7039811323 100644 --- a/ssl/ssl_ciph.c +++ b/ssl/ssl_ciph.c -@@ -1467,11 +1467,29 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_ +@@ -1467,11 +1467,29 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method, ssl_cipher_apply_rule(0, SSL_kECDHE, 0, 0, 0, 0, 0, CIPHER_DEL, -1, &head, &tail); @@ -67,7 +71,7 @@ Signed-off-by: Eneas U de Queiroz /* * ...and generally, our preferred cipher is AES. -@@ -1527,7 +1545,7 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_ +@@ -1527,7 +1545,7 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method, * Within each group, ciphers remain sorted by strength and previous * preference, i.e., * 1) ECDHE > DHE diff --git a/package/libs/openssl/patches/400-eng_devcrypto-save-ioctl-if-EVP_MD_.FLAG_ONESHOT.patch b/package/libs/openssl/patches/400-eng_devcrypto-save-ioctl-if-EVP_MD_.FLAG_ONESHOT.patch index 57962ec9c7..84c68b16a2 100644 --- a/package/libs/openssl/patches/400-eng_devcrypto-save-ioctl-if-EVP_MD_.FLAG_ONESHOT.patch +++ b/package/libs/openssl/patches/400-eng_devcrypto-save-ioctl-if-EVP_MD_.FLAG_ONESHOT.patch @@ -14,6 +14,8 @@ Reviewed-by: Matthias St. Pierre Reviewed-by: Richard Levitte (Merged from https://github.com/openssl/openssl/pull/7585) +diff --git a/crypto/engine/eng_devcrypto.c b/crypto/engine/eng_devcrypto.c +index a727c6f646..a2c9a966f7 100644 --- a/crypto/engine/eng_devcrypto.c +++ b/crypto/engine/eng_devcrypto.c @@ -461,6 +461,7 @@ struct digest_ctx { @@ -24,7 +26,7 @@ Reviewed-by: Richard Levitte }; static const struct digest_data_st { -@@ -564,12 +565,15 @@ static int digest_update(EVP_MD_CTX *ctx +@@ -564,12 +565,15 @@ static int digest_update(EVP_MD_CTX *ctx, const void *data, size_t count) if (digest_ctx == NULL) return 0; @@ -44,7 +46,7 @@ Reviewed-by: Richard Levitte } static int digest_final(EVP_MD_CTX *ctx, unsigned char *md) -@@ -579,7 +583,10 @@ static int digest_final(EVP_MD_CTX *ctx, +@@ -579,7 +583,10 @@ static int digest_final(EVP_MD_CTX *ctx, unsigned char *md) if (md == NULL || digest_ctx == NULL) return 0; diff --git a/package/libs/openssl/patches/410-eng_devcrypto-add-configuration-options.patch b/package/libs/openssl/patches/410-eng_devcrypto-add-configuration-options.patch index 12fe7b4199..8745364cf2 100644 --- a/package/libs/openssl/patches/410-eng_devcrypto-add-configuration-options.patch +++ b/package/libs/openssl/patches/410-eng_devcrypto-add-configuration-options.patch @@ -13,6 +13,8 @@ Reviewed-by: Matthias St. Pierre Reviewed-by: Richard Levitte (Merged from https://github.com/openssl/openssl/pull/7585) +diff --git a/crypto/engine/eng_devcrypto.c b/crypto/engine/eng_devcrypto.c +index a2c9a966f7..5ec38ca8f3 100644 --- a/crypto/engine/eng_devcrypto.c +++ b/crypto/engine/eng_devcrypto.c @@ -16,6 +16,7 @@ @@ -78,7 +80,7 @@ Reviewed-by: Richard Levitte /* * Code further down must make sure that only NIDs in the table above -@@ -333,19 +367,40 @@ static int cipher_cleanup(EVP_CIPHER_CTX +@@ -333,19 +367,40 @@ static int cipher_cleanup(EVP_CIPHER_CTX *ctx) } /* @@ -184,7 +186,7 @@ Reviewed-by: Richard Levitte static const EVP_CIPHER *get_cipher_method(int nid) { size_t i = get_cipher_data_index(nid); -@@ -438,6 +520,36 @@ static int devcrypto_ciphers(ENGINE *e, +@@ -438,6 +520,36 @@ static int devcrypto_ciphers(ENGINE *e, const EVP_CIPHER **cipher, return *cipher != NULL; } @@ -245,7 +247,7 @@ Reviewed-by: Richard Levitte /* * Code further down must make sure that only NIDs in the table above -@@ -516,8 +637,8 @@ static const struct digest_data_st *get_ +@@ -516,8 +637,8 @@ static const struct digest_data_st *get_digest_data(int nid) } /* @@ -256,7 +258,7 @@ Reviewed-by: Richard Levitte */ static int digest_init(EVP_MD_CTX *ctx) -@@ -630,52 +751,94 @@ static int digest_cleanup(EVP_MD_CTX *ct +@@ -630,52 +751,94 @@ static int digest_cleanup(EVP_MD_CTX *ctx) return clean_devcrypto_session(&digest_ctx->sess); } @@ -401,7 +403,7 @@ Reviewed-by: Richard Levitte } } -@@ -739,7 +909,153 @@ static int devcrypto_digests(ENGINE *e, +@@ -739,8 +909,154 @@ static int devcrypto_digests(ENGINE *e, const EVP_MD **digest, return *digest != NULL; } @@ -477,8 +479,8 @@ Reviewed-by: Richard Levitte + "DIGESTS", + "either ALL, NONE, or a comma-separated list of digests to enable [default=ALL]", + ENGINE_CMD_FLAG_STRING}, -+#endif -+ + #endif + + {0, NULL, NULL, 0} +}; + @@ -502,7 +504,7 @@ Reviewed-by: Richard Levitte + use_softdrivers = i; +#ifdef IMPLEMENT_DIGEST + rebuild_known_digest_nids(e); - #endif ++#endif + rebuild_known_cipher_nids(e); + return 1; +#endif /* CIOCGSESSINFO */ @@ -552,9 +554,10 @@ Reviewed-by: Richard Levitte + } + return 0; +} - ++ /****************************************************************************** * + * LOAD / UNLOAD @@ -793,6 +1109,8 @@ void engine_load_devcrypto_int() if (!ENGINE_set_id(e, "devcrypto") diff --git a/package/libs/openssl/patches/420-eng_devcrypto-add-command-to-dump-driver-info.patch b/package/libs/openssl/patches/420-eng_devcrypto-add-command-to-dump-driver-info.patch index b7e1f6a411..ad83a51a10 100644 --- a/package/libs/openssl/patches/420-eng_devcrypto-add-command-to-dump-driver-info.patch +++ b/package/libs/openssl/patches/420-eng_devcrypto-add-command-to-dump-driver-info.patch @@ -11,9 +11,11 @@ Reviewed-by: Matthias St. Pierre Reviewed-by: Richard Levitte (Merged from https://github.com/openssl/openssl/pull/7585) +diff --git a/crypto/engine/eng_devcrypto.c b/crypto/engine/eng_devcrypto.c +index 5ec38ca8f3..64dc6b891d 100644 --- a/crypto/engine/eng_devcrypto.c +++ b/crypto/engine/eng_devcrypto.c -@@ -50,16 +50,20 @@ static int use_softdrivers = DEVCRYPTO_D +@@ -50,16 +50,20 @@ static int use_softdrivers = DEVCRYPTO_DEFAULT_USE_SOFDTRIVERS; */ struct driver_info_st { enum devcrypto_status_t { @@ -80,7 +82,7 @@ Reviewed-by: Richard Levitte #endif /* CIOCGSESSINFO */ } ioctl(cfd, CIOCFSESSION, &sess.ses); -@@ -505,8 +514,11 @@ static void destroy_all_cipher_methods(v +@@ -505,8 +514,11 @@ static void destroy_all_cipher_methods(void) { size_t i; @@ -93,7 +95,7 @@ Reviewed-by: Richard Levitte } static int devcrypto_ciphers(ENGINE *e, const EVP_CIPHER **cipher, -@@ -550,6 +562,40 @@ static int cryptodev_select_cipher_cb(co +@@ -550,6 +562,40 @@ static int cryptodev_select_cipher_cb(const char *str, int len, void *usr) return 1; } @@ -188,7 +190,7 @@ Reviewed-by: Richard Levitte EVP_MD_meth_free(known_digest_methods[i]); known_digest_methods[i] = NULL; goto finish; -@@ -894,8 +945,11 @@ static void destroy_all_digest_methods(v +@@ -894,8 +945,11 @@ static void destroy_all_digest_methods(void) { size_t i; @@ -201,7 +203,7 @@ Reviewed-by: Richard Levitte } static int devcrypto_digests(ENGINE *e, const EVP_MD **digest, -@@ -939,6 +993,43 @@ static int cryptodev_select_digest_cb(co +@@ -939,6 +993,43 @@ static int cryptodev_select_digest_cb(const char *str, int len, void *usr) return 1; } @@ -245,7 +247,7 @@ Reviewed-by: Richard Levitte #endif /****************************************************************************** -@@ -983,6 +1074,11 @@ static const ENGINE_CMD_DEFN devcrypto_c +@@ -983,6 +1074,11 @@ static const ENGINE_CMD_DEFN devcrypto_cmds[] = { ENGINE_CMD_FLAG_STRING}, #endif @@ -257,7 +259,7 @@ Reviewed-by: Richard Levitte {0, NULL, NULL, 0} }; -@@ -1051,6 +1147,13 @@ static int devcrypto_ctrl(ENGINE *e, int +@@ -1051,6 +1147,13 @@ static int devcrypto_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void)) return 1; #endif /* IMPLEMENT_DIGEST */ diff --git a/package/libs/openssl/patches/430-e_devcrypto-make-the-dev-crypto-engine-dynamic.patch b/package/libs/openssl/patches/430-e_devcrypto-make-the-dev-crypto-engine-dynamic.patch index 4218fbe76c..71dc5bf99b 100644 --- a/package/libs/openssl/patches/430-e_devcrypto-make-the-dev-crypto-engine-dynamic.patch +++ b/package/libs/openssl/patches/430-e_devcrypto-make-the-dev-crypto-engine-dynamic.patch @@ -8,6 +8,8 @@ engines/e_devcrypto.c. Signed-off-by: Eneas U de Queiroz +diff --git a/crypto/engine/build.info b/crypto/engine/build.info +index e00802a3fd..47fe948966 100644 --- a/crypto/engine/build.info +++ b/crypto/engine/build.info @@ -6,6 +6,3 @@ SOURCE[../../libcrypto]=\ @@ -17,9 +19,11 @@ Signed-off-by: Eneas U de Queiroz -IF[{- !$disabled{devcryptoeng} -}] - SOURCE[../../libcrypto]=eng_devcrypto.c -ENDIF +diff --git a/crypto/init.c b/crypto/init.c +index 1b0d523bea..ee3e2eb075 100644 --- a/crypto/init.c +++ b/crypto/init.c -@@ -329,18 +329,6 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_engine_ +@@ -329,18 +329,6 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_engine_openssl) engine_load_openssl_int(); return 1; } @@ -38,7 +42,7 @@ Signed-off-by: Eneas U de Queiroz # ifndef OPENSSL_NO_RDRAND static CRYPTO_ONCE engine_rdrand = CRYPTO_ONCE_STATIC_INIT; -@@ -365,6 +353,18 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_engine_ +@@ -365,6 +353,18 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_engine_dynamic) return 1; } # ifndef OPENSSL_NO_STATIC_ENGINE @@ -57,7 +61,7 @@ Signed-off-by: Eneas U de Queiroz # if !defined(OPENSSL_NO_HW) && !defined(OPENSSL_NO_HW_PADLOCK) static CRYPTO_ONCE engine_padlock = CRYPTO_ONCE_STATIC_INIT; DEFINE_RUN_ONCE_STATIC(ossl_init_engine_padlock) -@@ -713,11 +713,6 @@ int OPENSSL_init_crypto(uint64_t opts, c +@@ -713,11 +713,6 @@ int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings) if ((opts & OPENSSL_INIT_ENGINE_OPENSSL) && !RUN_ONCE(&engine_openssl, ossl_init_engine_openssl)) return 0; @@ -69,7 +73,7 @@ Signed-off-by: Eneas U de Queiroz # ifndef OPENSSL_NO_RDRAND if ((opts & OPENSSL_INIT_ENGINE_RDRAND) && !RUN_ONCE(&engine_rdrand, ossl_init_engine_rdrand)) -@@ -727,6 +722,11 @@ int OPENSSL_init_crypto(uint64_t opts, c +@@ -727,6 +722,11 @@ int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings) && !RUN_ONCE(&engine_dynamic, ossl_init_engine_dynamic)) return 0; # ifndef OPENSSL_NO_STATIC_ENGINE @@ -81,6 +85,8 @@ Signed-off-by: Eneas U de Queiroz # if !defined(OPENSSL_NO_HW) && !defined(OPENSSL_NO_HW_PADLOCK) if ((opts & OPENSSL_INIT_ENGINE_PADLOCK) && !RUN_ONCE(&engine_padlock, ossl_init_engine_padlock)) +diff --git a/engines/build.info b/engines/build.info +index 1db771971c..33a25d7004 100644 --- a/engines/build.info +++ b/engines/build.info @@ -11,6 +11,9 @@ IF[{- !$disabled{"engine"} -}] @@ -106,1177 +112,75 @@ Signed-off-by: Eneas U de Queiroz ENGINES_NO_INST=ossltest dasync SOURCE[dasync]=e_dasync.c +diff --git a/crypto/engine/eng_devcrypto.c b/engines/e_devcrypto.c +similarity index 95% +rename from crypto/engine/eng_devcrypto.c +rename to engines/e_devcrypto.c +index 0d420e50aa..3fcd81de7a 100644 --- a/crypto/engine/eng_devcrypto.c -+++ /dev/null -@@ -1,1264 +0,0 @@ --/* -- * Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved. -- * -- * Licensed under the OpenSSL license (the "License"). You may not use -- * this file except in compliance with the License. You can obtain a copy -- * in the file LICENSE in the source distribution or at -- * https://www.openssl.org/source/license.html -- */ -- ++++ b/engines/e_devcrypto.c +@@ -7,7 +7,7 @@ + * https://www.openssl.org/source/license.html + */ + -#include "e_os.h" --#include --#include --#include --#include --#include --#include --#include -- --#include --#include --#include --#include --#include --#include -- --#include "crypto/engine.h" -- --/* #define ENGINE_DEVCRYPTO_DEBUG */ -- --#if CRYPTO_ALGORITHM_MIN < CRYPTO_ALGORITHM_MAX --# define CHECK_BSD_STYLE_MACROS --#endif -- --/* -- * ONE global file descriptor for all sessions. This allows operations -- * such as digest session data copying (see digest_copy()), but is also -- * saner... why re-open /dev/crypto for every session? -- */ ++#include "../e_os.h" + #include + #include + #include +@@ -31,18 +31,20 @@ + # define CHECK_BSD_STYLE_MACROS + #endif + ++#define engine_devcrypto_id "devcrypto" ++ + /* + * ONE global file descriptor for all sessions. This allows operations + * such as digest session data copying (see digest_copy()), but is also + * saner... why re-open /dev/crypto for every session? + */ -static int cfd; --#define DEVCRYPTO_REQUIRE_ACCELERATED 0 /* require confirmation of acceleration */ --#define DEVCRYPTO_USE_SOFTWARE 1 /* allow software drivers */ --#define DEVCRYPTO_REJECT_SOFTWARE 2 /* only disallow confirmed software drivers */ -- ++static int cfd = -1; + #define DEVCRYPTO_REQUIRE_ACCELERATED 0 /* require confirmation of acceleration */ + #define DEVCRYPTO_USE_SOFTWARE 1 /* allow software drivers */ + #define DEVCRYPTO_REJECT_SOFTWARE 2 /* only disallow confirmed software drivers */ + -#define DEVCRYPTO_DEFAULT_USE_SOFDTRIVERS DEVCRYPTO_REJECT_SOFTWARE -static int use_softdrivers = DEVCRYPTO_DEFAULT_USE_SOFDTRIVERS; -- --/* -- * cipher/digest status & acceleration definitions -- * Make sure the defaults are set to 0 -- */ --struct driver_info_st { -- enum devcrypto_status_t { -- DEVCRYPTO_STATUS_FAILURE = -3, /* unusable for other reason */ -- DEVCRYPTO_STATUS_NO_CIOCCPHASH = -2, /* hash state copy not supported */ -- DEVCRYPTO_STATUS_NO_CIOCGSESSION = -1, /* session open failed */ -- DEVCRYPTO_STATUS_UNKNOWN = 0, /* not tested yet */ -- DEVCRYPTO_STATUS_USABLE = 1 /* algo can be used */ -- } status; -- -- enum devcrypto_accelerated_t { -- DEVCRYPTO_NOT_ACCELERATED = -1, /* software implemented */ -- DEVCRYPTO_ACCELERATION_UNKNOWN = 0, /* acceleration support unkown */ -- DEVCRYPTO_ACCELERATED = 1 /* hardware accelerated */ -- } accelerated; -- -- char *driver_name; --}; -- --static int clean_devcrypto_session(struct session_op *sess) { -- if (ioctl(cfd, CIOCFSESSION, &sess->ses) < 0) { -- SYSerr(SYS_F_IOCTL, errno); -- return 0; -- } -- memset(sess, 0, sizeof(struct session_op)); -- return 1; --} -- --/****************************************************************************** -- * -- * Ciphers -- * -- * Because they all do the same basic operation, we have only one set of -- * method functions for them all to share, and a mapping table between -- * NIDs and cryptodev IDs, with all the necessary size data. -- * -- *****/ -- --struct cipher_ctx { -- struct session_op sess; -- int op; /* COP_ENCRYPT or COP_DECRYPT */ -- unsigned long mode; /* EVP_CIPH_*_MODE */ -- -- /* to handle ctr mode being a stream cipher */ -- unsigned char partial[EVP_MAX_BLOCK_LENGTH]; -- unsigned int blocksize, num; --}; -- --static const struct cipher_data_st { -- int nid; -- int blocksize; -- int keylen; -- int ivlen; -- int flags; -- int devcryptoid; --} cipher_data[] = { --#ifndef OPENSSL_NO_DES -- { NID_des_cbc, 8, 8, 8, EVP_CIPH_CBC_MODE, CRYPTO_DES_CBC }, -- { NID_des_ede3_cbc, 8, 24, 8, EVP_CIPH_CBC_MODE, CRYPTO_3DES_CBC }, --#endif --#ifndef OPENSSL_NO_BF -- { NID_bf_cbc, 8, 16, 8, EVP_CIPH_CBC_MODE, CRYPTO_BLF_CBC }, --#endif --#ifndef OPENSSL_NO_CAST -- { NID_cast5_cbc, 8, 16, 8, EVP_CIPH_CBC_MODE, CRYPTO_CAST_CBC }, --#endif -- { NID_aes_128_cbc, 16, 128 / 8, 16, EVP_CIPH_CBC_MODE, CRYPTO_AES_CBC }, -- { NID_aes_192_cbc, 16, 192 / 8, 16, EVP_CIPH_CBC_MODE, CRYPTO_AES_CBC }, -- { NID_aes_256_cbc, 16, 256 / 8, 16, EVP_CIPH_CBC_MODE, CRYPTO_AES_CBC }, --#ifndef OPENSSL_NO_RC4 -- { NID_rc4, 1, 16, 0, EVP_CIPH_STREAM_CIPHER, CRYPTO_ARC4 }, --#endif --#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_AES_CTR) -- { NID_aes_128_ctr, 16, 128 / 8, 16, EVP_CIPH_CTR_MODE, CRYPTO_AES_CTR }, -- { NID_aes_192_ctr, 16, 192 / 8, 16, EVP_CIPH_CTR_MODE, CRYPTO_AES_CTR }, -- { NID_aes_256_ctr, 16, 256 / 8, 16, EVP_CIPH_CTR_MODE, CRYPTO_AES_CTR }, --#endif --#if 0 /* Not yet supported */ -- { NID_aes_128_xts, 16, 128 / 8 * 2, 16, EVP_CIPH_XTS_MODE, CRYPTO_AES_XTS }, -- { NID_aes_256_xts, 16, 256 / 8 * 2, 16, EVP_CIPH_XTS_MODE, CRYPTO_AES_XTS }, --#endif --#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_AES_ECB) -- { NID_aes_128_ecb, 16, 128 / 8, 0, EVP_CIPH_ECB_MODE, CRYPTO_AES_ECB }, -- { NID_aes_192_ecb, 16, 192 / 8, 0, EVP_CIPH_ECB_MODE, CRYPTO_AES_ECB }, -- { NID_aes_256_ecb, 16, 256 / 8, 0, EVP_CIPH_ECB_MODE, CRYPTO_AES_ECB }, --#endif --#if 0 /* Not yet supported */ -- { NID_aes_128_gcm, 16, 128 / 8, 16, EVP_CIPH_GCM_MODE, CRYPTO_AES_GCM }, -- { NID_aes_192_gcm, 16, 192 / 8, 16, EVP_CIPH_GCM_MODE, CRYPTO_AES_GCM }, -- { NID_aes_256_gcm, 16, 256 / 8, 16, EVP_CIPH_GCM_MODE, CRYPTO_AES_GCM }, --#endif --#ifndef OPENSSL_NO_CAMELLIA -- { NID_camellia_128_cbc, 16, 128 / 8, 16, EVP_CIPH_CBC_MODE, -- CRYPTO_CAMELLIA_CBC }, -- { NID_camellia_192_cbc, 16, 192 / 8, 16, EVP_CIPH_CBC_MODE, -- CRYPTO_CAMELLIA_CBC }, -- { NID_camellia_256_cbc, 16, 256 / 8, 16, EVP_CIPH_CBC_MODE, -- CRYPTO_CAMELLIA_CBC }, --#endif --}; -- --static size_t find_cipher_data_index(int nid) --{ -- size_t i; -- -- for (i = 0; i < OSSL_NELEM(cipher_data); i++) -- if (nid == cipher_data[i].nid) -- return i; -- return (size_t)-1; --} -- --static size_t get_cipher_data_index(int nid) --{ -- size_t i = find_cipher_data_index(nid); -- -- if (i != (size_t)-1) -- return i; -- -- /* -- * Code further down must make sure that only NIDs in the table above -- * are used. If any other NID reaches this function, there's a grave -- * coding error further down. -- */ -- assert("Code that never should be reached" == NULL); -- return -1; --} -- --static const struct cipher_data_st *get_cipher_data(int nid) --{ -- return &cipher_data[get_cipher_data_index(nid)]; --} -- --/* -- * Following are the three necessary functions to map OpenSSL functionality -- * with cryptodev. -- */ -- --static int cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, -- const unsigned char *iv, int enc) --{ -- struct cipher_ctx *cipher_ctx = -- (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx); -- const struct cipher_data_st *cipher_d = -- get_cipher_data(EVP_CIPHER_CTX_nid(ctx)); -- -- /* cleanup a previous session */ -- if (cipher_ctx->sess.ses != 0 && -- clean_devcrypto_session(&cipher_ctx->sess) == 0) -- return 0; -- -- cipher_ctx->sess.cipher = cipher_d->devcryptoid; -- cipher_ctx->sess.keylen = cipher_d->keylen; -- cipher_ctx->sess.key = (void *)key; -- cipher_ctx->op = enc ? COP_ENCRYPT : COP_DECRYPT; -- cipher_ctx->mode = cipher_d->flags & EVP_CIPH_MODE; -- cipher_ctx->blocksize = cipher_d->blocksize; -- if (ioctl(cfd, CIOCGSESSION, &cipher_ctx->sess) < 0) { -- SYSerr(SYS_F_IOCTL, errno); -- return 0; -- } -- -- return 1; --} -- --static int cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, -- const unsigned char *in, size_t inl) --{ -- struct cipher_ctx *cipher_ctx = -- (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx); -- struct crypt_op cryp; -- unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx); --#if !defined(COP_FLAG_WRITE_IV) -- unsigned char saved_iv[EVP_MAX_IV_LENGTH]; -- const unsigned char *ivptr; -- size_t nblocks, ivlen; --#endif -- -- memset(&cryp, 0, sizeof(cryp)); -- cryp.ses = cipher_ctx->sess.ses; -- cryp.len = inl; -- cryp.src = (void *)in; -- cryp.dst = (void *)out; -- cryp.iv = (void *)iv; -- cryp.op = cipher_ctx->op; --#if !defined(COP_FLAG_WRITE_IV) -- cryp.flags = 0; -- -- ivlen = EVP_CIPHER_CTX_iv_length(ctx); -- if (ivlen > 0) -- switch (cipher_ctx->mode) { -- case EVP_CIPH_CBC_MODE: -- assert(inl >= ivlen); -- if (!EVP_CIPHER_CTX_encrypting(ctx)) { -- ivptr = in + inl - ivlen; -- memcpy(saved_iv, ivptr, ivlen); -- } -- break; -- -- case EVP_CIPH_CTR_MODE: -- break; -- -- default: /* should not happen */ -- return 0; -- } --#else -- cryp.flags = COP_FLAG_WRITE_IV; --#endif -- -- if (ioctl(cfd, CIOCCRYPT, &cryp) < 0) { -- SYSerr(SYS_F_IOCTL, errno); -- return 0; -- } -- --#if !defined(COP_FLAG_WRITE_IV) -- if (ivlen > 0) -- switch (cipher_ctx->mode) { -- case EVP_CIPH_CBC_MODE: -- assert(inl >= ivlen); -- if (EVP_CIPHER_CTX_encrypting(ctx)) -- ivptr = out + inl - ivlen; -- else -- ivptr = saved_iv; -- -- memcpy(iv, ivptr, ivlen); -- break; -- -- case EVP_CIPH_CTR_MODE: -- nblocks = (inl + cipher_ctx->blocksize - 1) -- / cipher_ctx->blocksize; -- do { -- ivlen--; -- nblocks += iv[ivlen]; -- iv[ivlen] = (uint8_t) nblocks; -- nblocks >>= 8; -- } while (ivlen); -- break; -- -- default: /* should not happen */ -- return 0; -- } --#endif -- -- return 1; --} -- --static int ctr_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, -- const unsigned char *in, size_t inl) --{ -- struct cipher_ctx *cipher_ctx = -- (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx); -- size_t nblocks, len; -- -- /* initial partial block */ -- while (cipher_ctx->num && inl) { -- (*out++) = *(in++) ^ cipher_ctx->partial[cipher_ctx->num]; -- --inl; -- cipher_ctx->num = (cipher_ctx->num + 1) % cipher_ctx->blocksize; -- } -- -- /* full blocks */ -- if (inl > (unsigned int) cipher_ctx->blocksize) { -- nblocks = inl/cipher_ctx->blocksize; -- len = nblocks * cipher_ctx->blocksize; -- if (cipher_do_cipher(ctx, out, in, len) < 1) -- return 0; -- inl -= len; -- out += len; -- in += len; -- } -- -- /* final partial block */ -- if (inl) { -- memset(cipher_ctx->partial, 0, cipher_ctx->blocksize); -- if (cipher_do_cipher(ctx, cipher_ctx->partial, cipher_ctx->partial, -- cipher_ctx->blocksize) < 1) -- return 0; -- while (inl--) { -- out[cipher_ctx->num] = in[cipher_ctx->num] -- ^ cipher_ctx->partial[cipher_ctx->num]; -- cipher_ctx->num++; -- } -- } -- -- return 1; --} -- --static int cipher_ctrl(EVP_CIPHER_CTX *ctx, int type, int p1, void* p2) --{ -- struct cipher_ctx *cipher_ctx = -- (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx); -- EVP_CIPHER_CTX *to_ctx = (EVP_CIPHER_CTX *)p2; -- struct cipher_ctx *to_cipher_ctx; -- -- switch (type) { -- case EVP_CTRL_COPY: -- if (cipher_ctx == NULL) -- return 1; -- /* when copying the context, a new session needs to be initialized */ -- to_cipher_ctx = -- (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(to_ctx); -- memset(&to_cipher_ctx->sess, 0, sizeof(to_cipher_ctx->sess)); -- return cipher_init(to_ctx, cipher_ctx->sess.key, EVP_CIPHER_CTX_iv(ctx), -- (cipher_ctx->op == COP_ENCRYPT)); -- -- case EVP_CTRL_INIT: -- memset(&cipher_ctx->sess, 0, sizeof(cipher_ctx->sess)); -- return 1; -- -- default: -- break; -- } -- -- return -1; --} -- --static int cipher_cleanup(EVP_CIPHER_CTX *ctx) --{ -- struct cipher_ctx *cipher_ctx = -- (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx); -- -- return clean_devcrypto_session(&cipher_ctx->sess); --} -- --/* -- * Keep tables of known nids, associated methods, selected ciphers, and driver -- * info. -- * Note that known_cipher_nids[] isn't necessarily indexed the same way as -- * cipher_data[] above, which the other tables are. -- */ --static int known_cipher_nids[OSSL_NELEM(cipher_data)]; --static int known_cipher_nids_amount = -1; /* -1 indicates not yet initialised */ --static EVP_CIPHER *known_cipher_methods[OSSL_NELEM(cipher_data)] = { NULL, }; --static int selected_ciphers[OSSL_NELEM(cipher_data)]; --static struct driver_info_st cipher_driver_info[OSSL_NELEM(cipher_data)]; -- -- --static int devcrypto_test_cipher(size_t cipher_data_index) --{ -- return (cipher_driver_info[cipher_data_index].status == DEVCRYPTO_STATUS_USABLE -- && selected_ciphers[cipher_data_index] == 1 -- && (cipher_driver_info[cipher_data_index].accelerated -- == DEVCRYPTO_ACCELERATED -- || use_softdrivers == DEVCRYPTO_USE_SOFTWARE -- || (cipher_driver_info[cipher_data_index].accelerated -- != DEVCRYPTO_NOT_ACCELERATED -- && use_softdrivers == DEVCRYPTO_REJECT_SOFTWARE))); --} -- --static void prepare_cipher_methods(void) --{ -- size_t i; -- struct session_op sess; -- unsigned long cipher_mode; --#ifdef CIOCGSESSINFO -- struct session_info_op siop; --#endif -- -- memset(&cipher_driver_info, 0, sizeof(cipher_driver_info)); -- -- memset(&sess, 0, sizeof(sess)); -- sess.key = (void *)"01234567890123456789012345678901234567890123456789"; -- -- for (i = 0, known_cipher_nids_amount = 0; -- i < OSSL_NELEM(cipher_data); i++) { -- -- selected_ciphers[i] = 1; -- /* -- * Check that the cipher is usable -- */ -- sess.cipher = cipher_data[i].devcryptoid; -- sess.keylen = cipher_data[i].keylen; -- if (ioctl(cfd, CIOCGSESSION, &sess) < 0) { -- cipher_driver_info[i].status = DEVCRYPTO_STATUS_NO_CIOCGSESSION; -- continue; -- } -- -- cipher_mode = cipher_data[i].flags & EVP_CIPH_MODE; -- -- if ((known_cipher_methods[i] = -- EVP_CIPHER_meth_new(cipher_data[i].nid, -- cipher_mode == EVP_CIPH_CTR_MODE ? 1 : -- cipher_data[i].blocksize, -- cipher_data[i].keylen)) == NULL -- || !EVP_CIPHER_meth_set_iv_length(known_cipher_methods[i], -- cipher_data[i].ivlen) -- || !EVP_CIPHER_meth_set_flags(known_cipher_methods[i], -- cipher_data[i].flags -- | EVP_CIPH_CUSTOM_COPY -- | EVP_CIPH_CTRL_INIT -- | EVP_CIPH_FLAG_DEFAULT_ASN1) -- || !EVP_CIPHER_meth_set_init(known_cipher_methods[i], cipher_init) -- || !EVP_CIPHER_meth_set_do_cipher(known_cipher_methods[i], -- cipher_mode == EVP_CIPH_CTR_MODE ? -- ctr_do_cipher : -- cipher_do_cipher) -- || !EVP_CIPHER_meth_set_ctrl(known_cipher_methods[i], cipher_ctrl) -- || !EVP_CIPHER_meth_set_cleanup(known_cipher_methods[i], -- cipher_cleanup) -- || !EVP_CIPHER_meth_set_impl_ctx_size(known_cipher_methods[i], -- sizeof(struct cipher_ctx))) { -- cipher_driver_info[i].status = DEVCRYPTO_STATUS_FAILURE; -- EVP_CIPHER_meth_free(known_cipher_methods[i]); -- known_cipher_methods[i] = NULL; -- } else { -- cipher_driver_info[i].status = DEVCRYPTO_STATUS_USABLE; --#ifdef CIOCGSESSINFO -- siop.ses = sess.ses; -- if (ioctl(cfd, CIOCGSESSINFO, &siop) < 0) { -- cipher_driver_info[i].accelerated = DEVCRYPTO_ACCELERATION_UNKNOWN; -- } else { -- cipher_driver_info[i].driver_name = -- OPENSSL_strndup(siop.cipher_info.cra_driver_name, -- CRYPTODEV_MAX_ALG_NAME); -- if (!(siop.flags & SIOP_FLAG_KERNEL_DRIVER_ONLY)) -- cipher_driver_info[i].accelerated = DEVCRYPTO_NOT_ACCELERATED; -- else -- cipher_driver_info[i].accelerated = DEVCRYPTO_ACCELERATED; -- } --#endif /* CIOCGSESSINFO */ -- } -- ioctl(cfd, CIOCFSESSION, &sess.ses); -- if (devcrypto_test_cipher(i)) { -- known_cipher_nids[known_cipher_nids_amount++] = -- cipher_data[i].nid; -- } -- } --} -- --static void rebuild_known_cipher_nids(ENGINE *e) --{ -- size_t i; -- -- for (i = 0, known_cipher_nids_amount = 0; i < OSSL_NELEM(cipher_data); i++) { -- if (devcrypto_test_cipher(i)) -- known_cipher_nids[known_cipher_nids_amount++] = cipher_data[i].nid; -- } -- ENGINE_unregister_ciphers(e); -- ENGINE_register_ciphers(e); --} -- --static const EVP_CIPHER *get_cipher_method(int nid) --{ -- size_t i = get_cipher_data_index(nid); -- -- if (i == (size_t)-1) -- return NULL; -- return known_cipher_methods[i]; --} -- --static int get_cipher_nids(const int **nids) --{ -- *nids = known_cipher_nids; -- return known_cipher_nids_amount; --} -- --static void destroy_cipher_method(int nid) --{ -- size_t i = get_cipher_data_index(nid); -- -- EVP_CIPHER_meth_free(known_cipher_methods[i]); -- known_cipher_methods[i] = NULL; --} -- --static void destroy_all_cipher_methods(void) --{ -- size_t i; -- -- for (i = 0; i < OSSL_NELEM(cipher_data); i++) { -- destroy_cipher_method(cipher_data[i].nid); -- OPENSSL_free(cipher_driver_info[i].driver_name); -- cipher_driver_info[i].driver_name = NULL; -- } --} -- --static int devcrypto_ciphers(ENGINE *e, const EVP_CIPHER **cipher, -- const int **nids, int nid) --{ -- if (cipher == NULL) -- return get_cipher_nids(nids); -- -- *cipher = get_cipher_method(nid); -- -- return *cipher != NULL; --} -- --static void devcrypto_select_all_ciphers(int *cipher_list) --{ -- size_t i; -- -- for (i = 0; i < OSSL_NELEM(cipher_data); i++) -- cipher_list[i] = 1; --} -- --static int cryptodev_select_cipher_cb(const char *str, int len, void *usr) --{ -- int *cipher_list = (int *)usr; -- char *name; -- const EVP_CIPHER *EVP; -- size_t i; -- -- if (len == 0) -- return 1; -- if (usr == NULL || (name = OPENSSL_strndup(str, len)) == NULL) -- return 0; -- EVP = EVP_get_cipherbyname(name); -- if (EVP == NULL) -- fprintf(stderr, "devcrypto: unknown cipher %s\n", name); -- else if ((i = find_cipher_data_index(EVP_CIPHER_nid(EVP))) != (size_t)-1) -- cipher_list[i] = 1; -- else -- fprintf(stderr, "devcrypto: cipher %s not available\n", name); -- OPENSSL_free(name); -- return 1; --} -- --static void dump_cipher_info(void) --{ -- size_t i; -- const char *name; -- -- fprintf (stderr, "Information about ciphers supported by the /dev/crypto" -- " engine:\n"); --#ifndef CIOCGSESSINFO -- fprintf(stderr, "CIOCGSESSINFO (session info call) unavailable\n"); --#endif -- for (i = 0; i < OSSL_NELEM(cipher_data); i++) { -- name = OBJ_nid2sn(cipher_data[i].nid); -- fprintf (stderr, "Cipher %s, NID=%d, /dev/crypto info: id=%d, ", -- name ? name : "unknown", cipher_data[i].nid, -- cipher_data[i].devcryptoid); -- if (cipher_driver_info[i].status == DEVCRYPTO_STATUS_NO_CIOCGSESSION ) { -- fprintf (stderr, "CIOCGSESSION (session open call) failed\n"); -- continue; -- } -- fprintf (stderr, "driver=%s ", cipher_driver_info[i].driver_name ? -- cipher_driver_info[i].driver_name : "unknown"); -- if (cipher_driver_info[i].accelerated == DEVCRYPTO_ACCELERATED) -- fprintf(stderr, "(hw accelerated)"); -- else if (cipher_driver_info[i].accelerated == DEVCRYPTO_NOT_ACCELERATED) -- fprintf(stderr, "(software)"); -- else -- fprintf(stderr, "(acceleration status unknown)"); -- if (cipher_driver_info[i].status == DEVCRYPTO_STATUS_FAILURE) -- fprintf (stderr, ". Cipher setup failed"); -- fprintf(stderr, "\n"); -- } -- fprintf(stderr, "\n"); --} -- --/* -- * We only support digests if the cryptodev implementation supports multiple -- * data updates and session copying. Otherwise, we would be forced to maintain -- * a cache, which is perilous if there's a lot of data coming in (if someone -- * wants to checksum an OpenSSL tarball, for example). -- */ --#if defined(CIOCCPHASH) && defined(COP_FLAG_UPDATE) && defined(COP_FLAG_FINAL) --#define IMPLEMENT_DIGEST -- --/****************************************************************************** -- * -- * Digests -- * -- * Because they all do the same basic operation, we have only one set of -- * method functions for them all to share, and a mapping table between -- * NIDs and cryptodev IDs, with all the necessary size data. -- * -- *****/ -- --struct digest_ctx { -- struct session_op sess; -- /* This signals that the init function was called, not that it succeeded. */ -- int init_called; -- unsigned char digest_res[HASH_MAX_LEN]; --}; -- --static const struct digest_data_st { -- int nid; -- int blocksize; -- int digestlen; -- int devcryptoid; --} digest_data[] = { --#ifndef OPENSSL_NO_MD5 -- { NID_md5, /* MD5_CBLOCK */ 64, 16, CRYPTO_MD5 }, --#endif -- { NID_sha1, SHA_CBLOCK, 20, CRYPTO_SHA1 }, --#ifndef OPENSSL_NO_RMD160 --# if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_RIPEMD160) -- { NID_ripemd160, /* RIPEMD160_CBLOCK */ 64, 20, CRYPTO_RIPEMD160 }, --# endif --#endif --#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_224) -- { NID_sha224, SHA256_CBLOCK, 224 / 8, CRYPTO_SHA2_224 }, --#endif --#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_256) -- { NID_sha256, SHA256_CBLOCK, 256 / 8, CRYPTO_SHA2_256 }, --#endif --#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_384) -- { NID_sha384, SHA512_CBLOCK, 384 / 8, CRYPTO_SHA2_384 }, --#endif --#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_512) -- { NID_sha512, SHA512_CBLOCK, 512 / 8, CRYPTO_SHA2_512 }, --#endif --}; -- --static size_t find_digest_data_index(int nid) --{ -- size_t i; -- -- for (i = 0; i < OSSL_NELEM(digest_data); i++) -- if (nid == digest_data[i].nid) -- return i; -- return (size_t)-1; --} -- --static size_t get_digest_data_index(int nid) --{ -- size_t i = find_digest_data_index(nid); -- -- if (i != (size_t)-1) -- return i; -- -- /* -- * Code further down must make sure that only NIDs in the table above -- * are used. If any other NID reaches this function, there's a grave -- * coding error further down. -- */ -- assert("Code that never should be reached" == NULL); -- return -1; --} -- --static const struct digest_data_st *get_digest_data(int nid) --{ -- return &digest_data[get_digest_data_index(nid)]; --} -- --/* -- * Following are the five necessary functions to map OpenSSL functionality -- * with cryptodev: init, update, final, cleanup, and copy. -- */ -- --static int digest_init(EVP_MD_CTX *ctx) --{ -- struct digest_ctx *digest_ctx = -- (struct digest_ctx *)EVP_MD_CTX_md_data(ctx); -- const struct digest_data_st *digest_d = -- get_digest_data(EVP_MD_CTX_type(ctx)); -- -- digest_ctx->init_called = 1; -- -- memset(&digest_ctx->sess, 0, sizeof(digest_ctx->sess)); -- digest_ctx->sess.mac = digest_d->devcryptoid; -- if (ioctl(cfd, CIOCGSESSION, &digest_ctx->sess) < 0) { -- SYSerr(SYS_F_IOCTL, errno); -- return 0; -- } -- -- return 1; --} -- --static int digest_op(struct digest_ctx *ctx, const void *src, size_t srclen, -- void *res, unsigned int flags) --{ -- struct crypt_op cryp; -- -- memset(&cryp, 0, sizeof(cryp)); -- cryp.ses = ctx->sess.ses; -- cryp.len = srclen; -- cryp.src = (void *)src; -- cryp.dst = NULL; -- cryp.mac = res; -- cryp.flags = flags; -- return ioctl(cfd, CIOCCRYPT, &cryp); --} -- --static int digest_update(EVP_MD_CTX *ctx, const void *data, size_t count) --{ -- struct digest_ctx *digest_ctx = -- (struct digest_ctx *)EVP_MD_CTX_md_data(ctx); -- -- if (count == 0) -- return 1; -- -- if (digest_ctx == NULL) -- return 0; -- -- if (EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_ONESHOT)) { -- if (digest_op(digest_ctx, data, count, digest_ctx->digest_res, 0) >= 0) -- return 1; -- } else if (digest_op(digest_ctx, data, count, NULL, COP_FLAG_UPDATE) >= 0) { -- return 1; -- } -- -- SYSerr(SYS_F_IOCTL, errno); -- return 0; --} -- --static int digest_final(EVP_MD_CTX *ctx, unsigned char *md) --{ -- struct digest_ctx *digest_ctx = -- (struct digest_ctx *)EVP_MD_CTX_md_data(ctx); -- -- if (md == NULL || digest_ctx == NULL) -- return 0; -- -- if (EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_ONESHOT)) { -- memcpy(md, digest_ctx->digest_res, EVP_MD_CTX_size(ctx)); -- } else if (digest_op(digest_ctx, NULL, 0, md, COP_FLAG_FINAL) < 0) { -- SYSerr(SYS_F_IOCTL, errno); -- return 0; -- } -- -- return 1; --} -- --static int digest_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from) --{ -- struct digest_ctx *digest_from = -- (struct digest_ctx *)EVP_MD_CTX_md_data(from); -- struct digest_ctx *digest_to = -- (struct digest_ctx *)EVP_MD_CTX_md_data(to); -- struct cphash_op cphash; -- -- if (digest_from == NULL || digest_from->init_called != 1) -- return 1; -- -- if (!digest_init(to)) { -- SYSerr(SYS_F_IOCTL, errno); -- return 0; -- } -- -- cphash.src_ses = digest_from->sess.ses; -- cphash.dst_ses = digest_to->sess.ses; -- if (ioctl(cfd, CIOCCPHASH, &cphash) < 0) { -- SYSerr(SYS_F_IOCTL, errno); -- return 0; -- } -- return 1; --} -- --static int digest_cleanup(EVP_MD_CTX *ctx) --{ -- struct digest_ctx *digest_ctx = -- (struct digest_ctx *)EVP_MD_CTX_md_data(ctx); -- -- if (digest_ctx == NULL) -- return 1; -- -- return clean_devcrypto_session(&digest_ctx->sess); --} -- --/* -- * Keep tables of known nids, associated methods, selected digests, and -- * driver info. -- * Note that known_digest_nids[] isn't necessarily indexed the same way as -- * digest_data[] above, which the other tables are. -- */ --static int known_digest_nids[OSSL_NELEM(digest_data)]; --static int known_digest_nids_amount = -1; /* -1 indicates not yet initialised */ --static EVP_MD *known_digest_methods[OSSL_NELEM(digest_data)] = { NULL, }; --static int selected_digests[OSSL_NELEM(digest_data)]; --static struct driver_info_st digest_driver_info[OSSL_NELEM(digest_data)]; -- --static int devcrypto_test_digest(size_t digest_data_index) --{ -- return (digest_driver_info[digest_data_index].status == DEVCRYPTO_STATUS_USABLE -- && selected_digests[digest_data_index] == 1 -- && (digest_driver_info[digest_data_index].accelerated -- == DEVCRYPTO_ACCELERATED -- || use_softdrivers == DEVCRYPTO_USE_SOFTWARE -- || (digest_driver_info[digest_data_index].accelerated -- != DEVCRYPTO_NOT_ACCELERATED -- && use_softdrivers == DEVCRYPTO_REJECT_SOFTWARE))); --} -- --static void rebuild_known_digest_nids(ENGINE *e) --{ -- size_t i; -- -- for (i = 0, known_digest_nids_amount = 0; i < OSSL_NELEM(digest_data); i++) { -- if (devcrypto_test_digest(i)) -- known_digest_nids[known_digest_nids_amount++] = digest_data[i].nid; -- } -- ENGINE_unregister_digests(e); -- ENGINE_register_digests(e); --} -- --static void prepare_digest_methods(void) --{ -- size_t i; -- struct session_op sess1, sess2; --#ifdef CIOCGSESSINFO -- struct session_info_op siop; --#endif -- struct cphash_op cphash; -- -- memset(&digest_driver_info, 0, sizeof(digest_driver_info)); -- -- memset(&sess1, 0, sizeof(sess1)); -- memset(&sess2, 0, sizeof(sess2)); -- -- for (i = 0, known_digest_nids_amount = 0; i < OSSL_NELEM(digest_data); -- i++) { -- -- selected_digests[i] = 1; -- -- /* -- * Check that the digest is usable -- */ -- sess1.mac = digest_data[i].devcryptoid; -- sess2.ses = 0; -- if (ioctl(cfd, CIOCGSESSION, &sess1) < 0) { -- digest_driver_info[i].status = DEVCRYPTO_STATUS_NO_CIOCGSESSION; -- goto finish; -- } -- --#ifdef CIOCGSESSINFO -- /* gather hardware acceleration info from the driver */ -- siop.ses = sess1.ses; -- if (ioctl(cfd, CIOCGSESSINFO, &siop) < 0) { -- digest_driver_info[i].accelerated = DEVCRYPTO_ACCELERATION_UNKNOWN; -- } else { -- digest_driver_info[i].driver_name = -- OPENSSL_strndup(siop.hash_info.cra_driver_name, -- CRYPTODEV_MAX_ALG_NAME); -- if (siop.flags & SIOP_FLAG_KERNEL_DRIVER_ONLY) -- digest_driver_info[i].accelerated = DEVCRYPTO_ACCELERATED; -- else -- digest_driver_info[i].accelerated = DEVCRYPTO_NOT_ACCELERATED; -- } --#endif -- -- /* digest must be capable of hash state copy */ -- sess2.mac = sess1.mac; -- if (ioctl(cfd, CIOCGSESSION, &sess2) < 0) { -- digest_driver_info[i].status = DEVCRYPTO_STATUS_FAILURE; -- goto finish; -- } -- cphash.src_ses = sess1.ses; -- cphash.dst_ses = sess2.ses; -- if (ioctl(cfd, CIOCCPHASH, &cphash) < 0) { -- digest_driver_info[i].status = DEVCRYPTO_STATUS_NO_CIOCCPHASH; -- goto finish; -- } -- if ((known_digest_methods[i] = EVP_MD_meth_new(digest_data[i].nid, -- NID_undef)) == NULL -- || !EVP_MD_meth_set_input_blocksize(known_digest_methods[i], -- digest_data[i].blocksize) -- || !EVP_MD_meth_set_result_size(known_digest_methods[i], -- digest_data[i].digestlen) -- || !EVP_MD_meth_set_init(known_digest_methods[i], digest_init) -- || !EVP_MD_meth_set_update(known_digest_methods[i], digest_update) -- || !EVP_MD_meth_set_final(known_digest_methods[i], digest_final) -- || !EVP_MD_meth_set_copy(known_digest_methods[i], digest_copy) -- || !EVP_MD_meth_set_cleanup(known_digest_methods[i], digest_cleanup) -- || !EVP_MD_meth_set_app_datasize(known_digest_methods[i], -- sizeof(struct digest_ctx))) { -- digest_driver_info[i].status = DEVCRYPTO_STATUS_FAILURE; -- EVP_MD_meth_free(known_digest_methods[i]); -- known_digest_methods[i] = NULL; -- goto finish; -- } -- digest_driver_info[i].status = DEVCRYPTO_STATUS_USABLE; --finish: -- ioctl(cfd, CIOCFSESSION, &sess1.ses); -- if (sess2.ses != 0) -- ioctl(cfd, CIOCFSESSION, &sess2.ses); -- if (devcrypto_test_digest(i)) -- known_digest_nids[known_digest_nids_amount++] = digest_data[i].nid; -- } --} -- --static const EVP_MD *get_digest_method(int nid) --{ -- size_t i = get_digest_data_index(nid); -- -- if (i == (size_t)-1) -- return NULL; -- return known_digest_methods[i]; --} -- --static int get_digest_nids(const int **nids) --{ -- *nids = known_digest_nids; -- return known_digest_nids_amount; --} -- --static void destroy_digest_method(int nid) --{ -- size_t i = get_digest_data_index(nid); -- -- EVP_MD_meth_free(known_digest_methods[i]); -- known_digest_methods[i] = NULL; --} -- --static void destroy_all_digest_methods(void) --{ -- size_t i; -- -- for (i = 0; i < OSSL_NELEM(digest_data); i++) { -- destroy_digest_method(digest_data[i].nid); -- OPENSSL_free(digest_driver_info[i].driver_name); -- digest_driver_info[i].driver_name = NULL; -- } --} -- --static int devcrypto_digests(ENGINE *e, const EVP_MD **digest, -- const int **nids, int nid) --{ -- if (digest == NULL) -- return get_digest_nids(nids); -- -- *digest = get_digest_method(nid); -- -- return *digest != NULL; --} -- --static void devcrypto_select_all_digests(int *digest_list) --{ -- size_t i; -- -- for (i = 0; i < OSSL_NELEM(digest_data); i++) -- digest_list[i] = 1; --} -- --static int cryptodev_select_digest_cb(const char *str, int len, void *usr) --{ -- int *digest_list = (int *)usr; -- char *name; -- const EVP_MD *EVP; -- size_t i; -- -- if (len == 0) -- return 1; -- if (usr == NULL || (name = OPENSSL_strndup(str, len)) == NULL) -- return 0; -- EVP = EVP_get_digestbyname(name); -- if (EVP == NULL) -- fprintf(stderr, "devcrypto: unknown digest %s\n", name); -- else if ((i = find_digest_data_index(EVP_MD_type(EVP))) != (size_t)-1) -- digest_list[i] = 1; -- else -- fprintf(stderr, "devcrypto: digest %s not available\n", name); -- OPENSSL_free(name); -- return 1; --} -- --static void dump_digest_info(void) --{ -- size_t i; -- const char *name; -- -- fprintf (stderr, "Information about digests supported by the /dev/crypto" -- " engine:\n"); --#ifndef CIOCGSESSINFO -- fprintf(stderr, "CIOCGSESSINFO (session info call) unavailable\n"); --#endif -- -- for (i = 0; i < OSSL_NELEM(digest_data); i++) { -- name = OBJ_nid2sn(digest_data[i].nid); -- fprintf (stderr, "Digest %s, NID=%d, /dev/crypto info: id=%d, driver=%s", -- name ? name : "unknown", digest_data[i].nid, -- digest_data[i].devcryptoid, -- digest_driver_info[i].driver_name ? digest_driver_info[i].driver_name : "unknown"); -- if (digest_driver_info[i].status == DEVCRYPTO_STATUS_NO_CIOCGSESSION) { -- fprintf (stderr, ". CIOCGSESSION (session open) failed\n"); -- continue; -- } -- if (digest_driver_info[i].accelerated == DEVCRYPTO_ACCELERATED) -- fprintf(stderr, " (hw accelerated)"); -- else if (digest_driver_info[i].accelerated == DEVCRYPTO_NOT_ACCELERATED) -- fprintf(stderr, " (software)"); -- else -- fprintf(stderr, " (acceleration status unknown)"); -- if (cipher_driver_info[i].status == DEVCRYPTO_STATUS_FAILURE) -- fprintf (stderr, ". Cipher setup failed\n"); -- else if (digest_driver_info[i].status == DEVCRYPTO_STATUS_NO_CIOCCPHASH) -- fprintf(stderr, ", CIOCCPHASH failed\n"); -- else -- fprintf(stderr, ", CIOCCPHASH capable\n"); -- } -- fprintf(stderr, "\n"); --} -- --#endif -- --/****************************************************************************** -- * -- * CONTROL COMMANDS -- * -- *****/ -- --#define DEVCRYPTO_CMD_USE_SOFTDRIVERS ENGINE_CMD_BASE --#define DEVCRYPTO_CMD_CIPHERS (ENGINE_CMD_BASE + 1) --#define DEVCRYPTO_CMD_DIGESTS (ENGINE_CMD_BASE + 2) --#define DEVCRYPTO_CMD_DUMP_INFO (ENGINE_CMD_BASE + 3) -- --/* Helper macros for CPP string composition */ --#ifndef OPENSSL_MSTR --# define OPENSSL_MSTR_HELPER(x) #x --# define OPENSSL_MSTR(x) OPENSSL_MSTR_HELPER(x) --#endif -- --static const ENGINE_CMD_DEFN devcrypto_cmds[] = { --#ifdef CIOCGSESSINFO -- {DEVCRYPTO_CMD_USE_SOFTDRIVERS, -- "USE_SOFTDRIVERS", -- "specifies whether to use software (not accelerated) drivers (" -- OPENSSL_MSTR(DEVCRYPTO_REQUIRE_ACCELERATED) "=use only accelerated drivers, " -- OPENSSL_MSTR(DEVCRYPTO_USE_SOFTWARE) "=allow all drivers, " -- OPENSSL_MSTR(DEVCRYPTO_REJECT_SOFTWARE) -- "=use if acceleration can't be determined) [default=" ++#define DEVCRYPTO_DEFAULT_USE_SOFTDRIVERS DEVCRYPTO_REJECT_SOFTWARE ++static int use_softdrivers = DEVCRYPTO_DEFAULT_USE_SOFTDRIVERS; + + /* + * cipher/digest status & acceleration definitions +@@ -341,6 +343,7 @@ static int cipher_ctrl(EVP_CIPHER_CTX *ctx, int type, int p1, void* p2) + struct cipher_ctx *to_cipher_ctx; + + switch (type) { ++ + case EVP_CTRL_COPY: + if (cipher_ctx == NULL) + return 1; +@@ -702,7 +705,6 @@ static int digest_init(EVP_MD_CTX *ctx) + SYSerr(SYS_F_IOCTL, errno); + return 0; + } +- + return 1; + } + +@@ -1058,7 +1060,7 @@ static const ENGINE_CMD_DEFN devcrypto_cmds[] = { + OPENSSL_MSTR(DEVCRYPTO_USE_SOFTWARE) "=allow all drivers, " + OPENSSL_MSTR(DEVCRYPTO_REJECT_SOFTWARE) + "=use if acceleration can't be determined) [default=" - OPENSSL_MSTR(DEVCRYPTO_DEFAULT_USE_SOFDTRIVERS) "]", -- ENGINE_CMD_FLAG_NUMERIC}, --#endif -- -- {DEVCRYPTO_CMD_CIPHERS, -- "CIPHERS", -- "either ALL, NONE, or a comma-separated list of ciphers to enable [default=ALL]", -- ENGINE_CMD_FLAG_STRING}, -- --#ifdef IMPLEMENT_DIGEST -- {DEVCRYPTO_CMD_DIGESTS, -- "DIGESTS", -- "either ALL, NONE, or a comma-separated list of digests to enable [default=ALL]", -- ENGINE_CMD_FLAG_STRING}, --#endif -- -- {DEVCRYPTO_CMD_DUMP_INFO, -- "DUMP_INFO", -- "dump info about each algorithm to stderr; use 'openssl engine -pre DUMP_INFO devcrypto'", -- ENGINE_CMD_FLAG_NO_INPUT}, -- -- {0, NULL, NULL, 0} --}; -- --static int devcrypto_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void)) --{ -- int *new_list; -- switch (cmd) { --#ifdef CIOCGSESSINFO -- case DEVCRYPTO_CMD_USE_SOFTDRIVERS: -- switch (i) { -- case DEVCRYPTO_REQUIRE_ACCELERATED: -- case DEVCRYPTO_USE_SOFTWARE: -- case DEVCRYPTO_REJECT_SOFTWARE: -- break; -- default: -- fprintf(stderr, "devcrypto: invalid value (%ld) for USE_SOFTDRIVERS\n", i); -- return 0; -- } -- if (use_softdrivers == i) -- return 1; -- use_softdrivers = i; --#ifdef IMPLEMENT_DIGEST -- rebuild_known_digest_nids(e); --#endif -- rebuild_known_cipher_nids(e); -- return 1; --#endif /* CIOCGSESSINFO */ -- -- case DEVCRYPTO_CMD_CIPHERS: -- if (p == NULL) -- return 1; -- if (strcasecmp((const char *)p, "ALL") == 0) { -- devcrypto_select_all_ciphers(selected_ciphers); -- } else if (strcasecmp((const char*)p, "NONE") == 0) { -- memset(selected_ciphers, 0, sizeof(selected_ciphers)); -- } else { -- new_list=OPENSSL_zalloc(sizeof(selected_ciphers)); -- if (!CONF_parse_list(p, ',', 1, cryptodev_select_cipher_cb, new_list)) { -- OPENSSL_free(new_list); -- return 0; -- } -- memcpy(selected_ciphers, new_list, sizeof(selected_ciphers)); -- OPENSSL_free(new_list); -- } -- rebuild_known_cipher_nids(e); -- return 1; -- --#ifdef IMPLEMENT_DIGEST -- case DEVCRYPTO_CMD_DIGESTS: -- if (p == NULL) -- return 1; -- if (strcasecmp((const char *)p, "ALL") == 0) { -- devcrypto_select_all_digests(selected_digests); -- } else if (strcasecmp((const char*)p, "NONE") == 0) { -- memset(selected_digests, 0, sizeof(selected_digests)); -- } else { -- new_list=OPENSSL_zalloc(sizeof(selected_digests)); -- if (!CONF_parse_list(p, ',', 1, cryptodev_select_digest_cb, new_list)) { -- OPENSSL_free(new_list); -- return 0; -- } -- memcpy(selected_digests, new_list, sizeof(selected_digests)); -- OPENSSL_free(new_list); -- } -- rebuild_known_digest_nids(e); -- return 1; --#endif /* IMPLEMENT_DIGEST */ -- -- case DEVCRYPTO_CMD_DUMP_INFO: -- dump_cipher_info(); --#ifdef IMPLEMENT_DIGEST -- dump_digest_info(); --#endif -- return 1; -- -- default: -- break; -- } -- return 0; --} -- --/****************************************************************************** -- * -- * LOAD / UNLOAD -- * -- *****/ -- ++ OPENSSL_MSTR(DEVCRYPTO_DEFAULT_USE_SOFTDRIVERS) "]", + ENGINE_CMD_FLAG_NUMERIC}, + #endif + +@@ -1166,55 +1168,70 @@ static int devcrypto_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void)) + * + *****/ + -static int devcrypto_unload(ENGINE *e) -{ - destroy_all_cipher_methods(); @@ -1288,22 +192,27 @@ Signed-off-by: Eneas U de Queiroz - - return 1; -} --/* + /* - * This engine is always built into libcrypto, so it doesn't offer any - * ability to be dynamically loadable. -- */ ++ * Opens /dev/crypto + */ -void engine_load_devcrypto_int() --{ ++static int open_devcrypto(void) + { - ENGINE *e = NULL; -- -- if ((cfd = open("/dev/crypto", O_RDWR, 0)) < 0) { --#ifndef ENGINE_DEVCRYPTO_DEBUG -- if (errno != ENOENT) --#endif -- fprintf(stderr, "Could not open /dev/crypto: %s\n", strerror(errno)); ++ if (cfd >= 0) ++ return 1; + + if ((cfd = open("/dev/crypto", O_RDWR, 0)) < 0) { + #ifndef ENGINE_DEVCRYPTO_DEBUG + if (errno != ENOENT) + #endif + fprintf(stderr, "Could not open /dev/crypto: %s\n", strerror(errno)); - return; -- } -- ++ return 0; + } + - if ((e = ENGINE_new()) == NULL - || !ENGINE_set_destroy_function(e, devcrypto_unload)) { - ENGINE_free(e); @@ -1314,1254 +223,6 @@ Signed-off-by: Eneas U de Queiroz - */ - close(cfd); - return; -- } -- -- prepare_cipher_methods(); --#ifdef IMPLEMENT_DIGEST -- prepare_digest_methods(); --#endif -- -- if (!ENGINE_set_id(e, "devcrypto") -- || !ENGINE_set_name(e, "/dev/crypto engine") -- || !ENGINE_set_cmd_defns(e, devcrypto_cmds) -- || !ENGINE_set_ctrl_function(e, devcrypto_ctrl) -- --/* -- * Asymmetric ciphers aren't well supported with /dev/crypto. Among the BSD -- * implementations, it seems to only exist in FreeBSD, and regarding the -- * parameters in its crypt_kop, the manual crypto(4) has this to say: -- * -- * The semantics of these arguments are currently undocumented. -- * -- * Reading through the FreeBSD source code doesn't give much more than -- * their CRK_MOD_EXP implementation for ubsec. -- * -- * It doesn't look much better with cryptodev-linux. They have the crypt_kop -- * structure as well as the command (CRK_*) in cryptodev.h, but no support -- * seems to be implemented at all for the moment. -- * -- * At the time of writing, it seems impossible to write proper support for -- * FreeBSD's asym features without some very deep knowledge and access to -- * specific kernel modules. -- * -- * /Richard Levitte, 2017-05-11 -- */ --#if 0 --# ifndef OPENSSL_NO_RSA -- || !ENGINE_set_RSA(e, devcrypto_rsa) --# endif --# ifndef OPENSSL_NO_DSA -- || !ENGINE_set_DSA(e, devcrypto_dsa) --# endif --# ifndef OPENSSL_NO_DH -- || !ENGINE_set_DH(e, devcrypto_dh) --# endif --# ifndef OPENSSL_NO_EC -- || !ENGINE_set_EC(e, devcrypto_ec) --# endif --#endif -- || !ENGINE_set_ciphers(e, devcrypto_ciphers) --#ifdef IMPLEMENT_DIGEST -- || !ENGINE_set_digests(e, devcrypto_digests) --#endif -- ) { -- ENGINE_free(e); -- return; -- } -- -- ENGINE_add(e); -- ENGINE_free(e); /* Loose our local reference */ -- ERR_clear_error(); --} ---- /dev/null -+++ b/engines/e_devcrypto.c -@@ -0,0 +1,1313 @@ -+/* -+ * Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved. -+ * -+ * Licensed under the OpenSSL license (the "License"). You may not use -+ * this file except in compliance with the License. You can obtain a copy -+ * in the file LICENSE in the source distribution or at -+ * https://www.openssl.org/source/license.html -+ */ -+ -+#include "../e_os.h" -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "crypto/engine.h" -+ -+/* #define ENGINE_DEVCRYPTO_DEBUG */ -+ -+#if CRYPTO_ALGORITHM_MIN < CRYPTO_ALGORITHM_MAX -+# define CHECK_BSD_STYLE_MACROS -+#endif -+ -+#define engine_devcrypto_id "devcrypto" -+ -+/* -+ * ONE global file descriptor for all sessions. This allows operations -+ * such as digest session data copying (see digest_copy()), but is also -+ * saner... why re-open /dev/crypto for every session? -+ */ -+static int cfd = -1; -+#define DEVCRYPTO_REQUIRE_ACCELERATED 0 /* require confirmation of acceleration */ -+#define DEVCRYPTO_USE_SOFTWARE 1 /* allow software drivers */ -+#define DEVCRYPTO_REJECT_SOFTWARE 2 /* only disallow confirmed software drivers */ -+ -+#define DEVCRYPTO_DEFAULT_USE_SOFTDRIVERS DEVCRYPTO_REJECT_SOFTWARE -+static int use_softdrivers = DEVCRYPTO_DEFAULT_USE_SOFTDRIVERS; -+ -+/* -+ * cipher/digest status & acceleration definitions -+ * Make sure the defaults are set to 0 -+ */ -+struct driver_info_st { -+ enum devcrypto_status_t { -+ DEVCRYPTO_STATUS_FAILURE = -3, /* unusable for other reason */ -+ DEVCRYPTO_STATUS_NO_CIOCCPHASH = -2, /* hash state copy not supported */ -+ DEVCRYPTO_STATUS_NO_CIOCGSESSION = -1, /* session open failed */ -+ DEVCRYPTO_STATUS_UNKNOWN = 0, /* not tested yet */ -+ DEVCRYPTO_STATUS_USABLE = 1 /* algo can be used */ -+ } status; -+ -+ enum devcrypto_accelerated_t { -+ DEVCRYPTO_NOT_ACCELERATED = -1, /* software implemented */ -+ DEVCRYPTO_ACCELERATION_UNKNOWN = 0, /* acceleration support unkown */ -+ DEVCRYPTO_ACCELERATED = 1 /* hardware accelerated */ -+ } accelerated; -+ -+ char *driver_name; -+}; -+ -+static int clean_devcrypto_session(struct session_op *sess) { -+ if (ioctl(cfd, CIOCFSESSION, &sess->ses) < 0) { -+ SYSerr(SYS_F_IOCTL, errno); -+ return 0; -+ } -+ memset(sess, 0, sizeof(struct session_op)); -+ return 1; -+} -+ -+/****************************************************************************** -+ * -+ * Ciphers -+ * -+ * Because they all do the same basic operation, we have only one set of -+ * method functions for them all to share, and a mapping table between -+ * NIDs and cryptodev IDs, with all the necessary size data. -+ * -+ *****/ -+ -+struct cipher_ctx { -+ struct session_op sess; -+ int op; /* COP_ENCRYPT or COP_DECRYPT */ -+ unsigned long mode; /* EVP_CIPH_*_MODE */ -+ -+ /* to handle ctr mode being a stream cipher */ -+ unsigned char partial[EVP_MAX_BLOCK_LENGTH]; -+ unsigned int blocksize, num; -+}; -+ -+static const struct cipher_data_st { -+ int nid; -+ int blocksize; -+ int keylen; -+ int ivlen; -+ int flags; -+ int devcryptoid; -+} cipher_data[] = { -+#ifndef OPENSSL_NO_DES -+ { NID_des_cbc, 8, 8, 8, EVP_CIPH_CBC_MODE, CRYPTO_DES_CBC }, -+ { NID_des_ede3_cbc, 8, 24, 8, EVP_CIPH_CBC_MODE, CRYPTO_3DES_CBC }, -+#endif -+#ifndef OPENSSL_NO_BF -+ { NID_bf_cbc, 8, 16, 8, EVP_CIPH_CBC_MODE, CRYPTO_BLF_CBC }, -+#endif -+#ifndef OPENSSL_NO_CAST -+ { NID_cast5_cbc, 8, 16, 8, EVP_CIPH_CBC_MODE, CRYPTO_CAST_CBC }, -+#endif -+ { NID_aes_128_cbc, 16, 128 / 8, 16, EVP_CIPH_CBC_MODE, CRYPTO_AES_CBC }, -+ { NID_aes_192_cbc, 16, 192 / 8, 16, EVP_CIPH_CBC_MODE, CRYPTO_AES_CBC }, -+ { NID_aes_256_cbc, 16, 256 / 8, 16, EVP_CIPH_CBC_MODE, CRYPTO_AES_CBC }, -+#ifndef OPENSSL_NO_RC4 -+ { NID_rc4, 1, 16, 0, EVP_CIPH_STREAM_CIPHER, CRYPTO_ARC4 }, -+#endif -+#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_AES_CTR) -+ { NID_aes_128_ctr, 16, 128 / 8, 16, EVP_CIPH_CTR_MODE, CRYPTO_AES_CTR }, -+ { NID_aes_192_ctr, 16, 192 / 8, 16, EVP_CIPH_CTR_MODE, CRYPTO_AES_CTR }, -+ { NID_aes_256_ctr, 16, 256 / 8, 16, EVP_CIPH_CTR_MODE, CRYPTO_AES_CTR }, -+#endif -+#if 0 /* Not yet supported */ -+ { NID_aes_128_xts, 16, 128 / 8 * 2, 16, EVP_CIPH_XTS_MODE, CRYPTO_AES_XTS }, -+ { NID_aes_256_xts, 16, 256 / 8 * 2, 16, EVP_CIPH_XTS_MODE, CRYPTO_AES_XTS }, -+#endif -+#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_AES_ECB) -+ { NID_aes_128_ecb, 16, 128 / 8, 0, EVP_CIPH_ECB_MODE, CRYPTO_AES_ECB }, -+ { NID_aes_192_ecb, 16, 192 / 8, 0, EVP_CIPH_ECB_MODE, CRYPTO_AES_ECB }, -+ { NID_aes_256_ecb, 16, 256 / 8, 0, EVP_CIPH_ECB_MODE, CRYPTO_AES_ECB }, -+#endif -+#if 0 /* Not yet supported */ -+ { NID_aes_128_gcm, 16, 128 / 8, 16, EVP_CIPH_GCM_MODE, CRYPTO_AES_GCM }, -+ { NID_aes_192_gcm, 16, 192 / 8, 16, EVP_CIPH_GCM_MODE, CRYPTO_AES_GCM }, -+ { NID_aes_256_gcm, 16, 256 / 8, 16, EVP_CIPH_GCM_MODE, CRYPTO_AES_GCM }, -+#endif -+#ifndef OPENSSL_NO_CAMELLIA -+ { NID_camellia_128_cbc, 16, 128 / 8, 16, EVP_CIPH_CBC_MODE, -+ CRYPTO_CAMELLIA_CBC }, -+ { NID_camellia_192_cbc, 16, 192 / 8, 16, EVP_CIPH_CBC_MODE, -+ CRYPTO_CAMELLIA_CBC }, -+ { NID_camellia_256_cbc, 16, 256 / 8, 16, EVP_CIPH_CBC_MODE, -+ CRYPTO_CAMELLIA_CBC }, -+#endif -+}; -+ -+static size_t find_cipher_data_index(int nid) -+{ -+ size_t i; -+ -+ for (i = 0; i < OSSL_NELEM(cipher_data); i++) -+ if (nid == cipher_data[i].nid) -+ return i; -+ return (size_t)-1; -+} -+ -+static size_t get_cipher_data_index(int nid) -+{ -+ size_t i = find_cipher_data_index(nid); -+ -+ if (i != (size_t)-1) -+ return i; -+ -+ /* -+ * Code further down must make sure that only NIDs in the table above -+ * are used. If any other NID reaches this function, there's a grave -+ * coding error further down. -+ */ -+ assert("Code that never should be reached" == NULL); -+ return -1; -+} -+ -+static const struct cipher_data_st *get_cipher_data(int nid) -+{ -+ return &cipher_data[get_cipher_data_index(nid)]; -+} -+ -+/* -+ * Following are the three necessary functions to map OpenSSL functionality -+ * with cryptodev. -+ */ -+ -+static int cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, -+ const unsigned char *iv, int enc) -+{ -+ struct cipher_ctx *cipher_ctx = -+ (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx); -+ const struct cipher_data_st *cipher_d = -+ get_cipher_data(EVP_CIPHER_CTX_nid(ctx)); -+ -+ /* cleanup a previous session */ -+ if (cipher_ctx->sess.ses != 0 && -+ clean_devcrypto_session(&cipher_ctx->sess) == 0) -+ return 0; -+ -+ cipher_ctx->sess.cipher = cipher_d->devcryptoid; -+ cipher_ctx->sess.keylen = cipher_d->keylen; -+ cipher_ctx->sess.key = (void *)key; -+ cipher_ctx->op = enc ? COP_ENCRYPT : COP_DECRYPT; -+ cipher_ctx->mode = cipher_d->flags & EVP_CIPH_MODE; -+ cipher_ctx->blocksize = cipher_d->blocksize; -+ if (ioctl(cfd, CIOCGSESSION, &cipher_ctx->sess) < 0) { -+ SYSerr(SYS_F_IOCTL, errno); -+ return 0; -+ } -+ -+ return 1; -+} -+ -+static int cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, -+ const unsigned char *in, size_t inl) -+{ -+ struct cipher_ctx *cipher_ctx = -+ (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx); -+ struct crypt_op cryp; -+ unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx); -+#if !defined(COP_FLAG_WRITE_IV) -+ unsigned char saved_iv[EVP_MAX_IV_LENGTH]; -+ const unsigned char *ivptr; -+ size_t nblocks, ivlen; -+#endif -+ -+ memset(&cryp, 0, sizeof(cryp)); -+ cryp.ses = cipher_ctx->sess.ses; -+ cryp.len = inl; -+ cryp.src = (void *)in; -+ cryp.dst = (void *)out; -+ cryp.iv = (void *)iv; -+ cryp.op = cipher_ctx->op; -+#if !defined(COP_FLAG_WRITE_IV) -+ cryp.flags = 0; -+ -+ ivlen = EVP_CIPHER_CTX_iv_length(ctx); -+ if (ivlen > 0) -+ switch (cipher_ctx->mode) { -+ case EVP_CIPH_CBC_MODE: -+ assert(inl >= ivlen); -+ if (!EVP_CIPHER_CTX_encrypting(ctx)) { -+ ivptr = in + inl - ivlen; -+ memcpy(saved_iv, ivptr, ivlen); -+ } -+ break; -+ -+ case EVP_CIPH_CTR_MODE: -+ break; -+ -+ default: /* should not happen */ -+ return 0; -+ } -+#else -+ cryp.flags = COP_FLAG_WRITE_IV; -+#endif -+ -+ if (ioctl(cfd, CIOCCRYPT, &cryp) < 0) { -+ SYSerr(SYS_F_IOCTL, errno); -+ return 0; -+ } -+ -+#if !defined(COP_FLAG_WRITE_IV) -+ if (ivlen > 0) -+ switch (cipher_ctx->mode) { -+ case EVP_CIPH_CBC_MODE: -+ assert(inl >= ivlen); -+ if (EVP_CIPHER_CTX_encrypting(ctx)) -+ ivptr = out + inl - ivlen; -+ else -+ ivptr = saved_iv; -+ -+ memcpy(iv, ivptr, ivlen); -+ break; -+ -+ case EVP_CIPH_CTR_MODE: -+ nblocks = (inl + cipher_ctx->blocksize - 1) -+ / cipher_ctx->blocksize; -+ do { -+ ivlen--; -+ nblocks += iv[ivlen]; -+ iv[ivlen] = (uint8_t) nblocks; -+ nblocks >>= 8; -+ } while (ivlen); -+ break; -+ -+ default: /* should not happen */ -+ return 0; -+ } -+#endif -+ -+ return 1; -+} -+ -+static int ctr_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, -+ const unsigned char *in, size_t inl) -+{ -+ struct cipher_ctx *cipher_ctx = -+ (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx); -+ size_t nblocks, len; -+ -+ /* initial partial block */ -+ while (cipher_ctx->num && inl) { -+ (*out++) = *(in++) ^ cipher_ctx->partial[cipher_ctx->num]; -+ --inl; -+ cipher_ctx->num = (cipher_ctx->num + 1) % cipher_ctx->blocksize; -+ } -+ -+ /* full blocks */ -+ if (inl > (unsigned int) cipher_ctx->blocksize) { -+ nblocks = inl/cipher_ctx->blocksize; -+ len = nblocks * cipher_ctx->blocksize; -+ if (cipher_do_cipher(ctx, out, in, len) < 1) -+ return 0; -+ inl -= len; -+ out += len; -+ in += len; -+ } -+ -+ /* final partial block */ -+ if (inl) { -+ memset(cipher_ctx->partial, 0, cipher_ctx->blocksize); -+ if (cipher_do_cipher(ctx, cipher_ctx->partial, cipher_ctx->partial, -+ cipher_ctx->blocksize) < 1) -+ return 0; -+ while (inl--) { -+ out[cipher_ctx->num] = in[cipher_ctx->num] -+ ^ cipher_ctx->partial[cipher_ctx->num]; -+ cipher_ctx->num++; -+ } -+ } -+ -+ return 1; -+} -+ -+static int cipher_ctrl(EVP_CIPHER_CTX *ctx, int type, int p1, void* p2) -+{ -+ struct cipher_ctx *cipher_ctx = -+ (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx); -+ EVP_CIPHER_CTX *to_ctx = (EVP_CIPHER_CTX *)p2; -+ struct cipher_ctx *to_cipher_ctx; -+ -+ switch (type) { -+ -+ case EVP_CTRL_COPY: -+ if (cipher_ctx == NULL) -+ return 1; -+ /* when copying the context, a new session needs to be initialized */ -+ to_cipher_ctx = -+ (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(to_ctx); -+ memset(&to_cipher_ctx->sess, 0, sizeof(to_cipher_ctx->sess)); -+ return cipher_init(to_ctx, cipher_ctx->sess.key, EVP_CIPHER_CTX_iv(ctx), -+ (cipher_ctx->op == COP_ENCRYPT)); -+ -+ case EVP_CTRL_INIT: -+ memset(&cipher_ctx->sess, 0, sizeof(cipher_ctx->sess)); -+ return 1; -+ -+ default: -+ break; -+ } -+ -+ return -1; -+} -+ -+static int cipher_cleanup(EVP_CIPHER_CTX *ctx) -+{ -+ struct cipher_ctx *cipher_ctx = -+ (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx); -+ -+ return clean_devcrypto_session(&cipher_ctx->sess); -+} -+ -+/* -+ * Keep tables of known nids, associated methods, selected ciphers, and driver -+ * info. -+ * Note that known_cipher_nids[] isn't necessarily indexed the same way as -+ * cipher_data[] above, which the other tables are. -+ */ -+static int known_cipher_nids[OSSL_NELEM(cipher_data)]; -+static int known_cipher_nids_amount = -1; /* -1 indicates not yet initialised */ -+static EVP_CIPHER *known_cipher_methods[OSSL_NELEM(cipher_data)] = { NULL, }; -+static int selected_ciphers[OSSL_NELEM(cipher_data)]; -+static struct driver_info_st cipher_driver_info[OSSL_NELEM(cipher_data)]; -+ -+ -+static int devcrypto_test_cipher(size_t cipher_data_index) -+{ -+ return (cipher_driver_info[cipher_data_index].status == DEVCRYPTO_STATUS_USABLE -+ && selected_ciphers[cipher_data_index] == 1 -+ && (cipher_driver_info[cipher_data_index].accelerated -+ == DEVCRYPTO_ACCELERATED -+ || use_softdrivers == DEVCRYPTO_USE_SOFTWARE -+ || (cipher_driver_info[cipher_data_index].accelerated -+ != DEVCRYPTO_NOT_ACCELERATED -+ && use_softdrivers == DEVCRYPTO_REJECT_SOFTWARE))); -+} -+ -+static void prepare_cipher_methods(void) -+{ -+ size_t i; -+ struct session_op sess; -+ unsigned long cipher_mode; -+#ifdef CIOCGSESSINFO -+ struct session_info_op siop; -+#endif -+ -+ memset(&cipher_driver_info, 0, sizeof(cipher_driver_info)); -+ -+ memset(&sess, 0, sizeof(sess)); -+ sess.key = (void *)"01234567890123456789012345678901234567890123456789"; -+ -+ for (i = 0, known_cipher_nids_amount = 0; -+ i < OSSL_NELEM(cipher_data); i++) { -+ -+ selected_ciphers[i] = 1; -+ /* -+ * Check that the cipher is usable -+ */ -+ sess.cipher = cipher_data[i].devcryptoid; -+ sess.keylen = cipher_data[i].keylen; -+ if (ioctl(cfd, CIOCGSESSION, &sess) < 0) { -+ cipher_driver_info[i].status = DEVCRYPTO_STATUS_NO_CIOCGSESSION; -+ continue; -+ } -+ -+ cipher_mode = cipher_data[i].flags & EVP_CIPH_MODE; -+ -+ if ((known_cipher_methods[i] = -+ EVP_CIPHER_meth_new(cipher_data[i].nid, -+ cipher_mode == EVP_CIPH_CTR_MODE ? 1 : -+ cipher_data[i].blocksize, -+ cipher_data[i].keylen)) == NULL -+ || !EVP_CIPHER_meth_set_iv_length(known_cipher_methods[i], -+ cipher_data[i].ivlen) -+ || !EVP_CIPHER_meth_set_flags(known_cipher_methods[i], -+ cipher_data[i].flags -+ | EVP_CIPH_CUSTOM_COPY -+ | EVP_CIPH_CTRL_INIT -+ | EVP_CIPH_FLAG_DEFAULT_ASN1) -+ || !EVP_CIPHER_meth_set_init(known_cipher_methods[i], cipher_init) -+ || !EVP_CIPHER_meth_set_do_cipher(known_cipher_methods[i], -+ cipher_mode == EVP_CIPH_CTR_MODE ? -+ ctr_do_cipher : -+ cipher_do_cipher) -+ || !EVP_CIPHER_meth_set_ctrl(known_cipher_methods[i], cipher_ctrl) -+ || !EVP_CIPHER_meth_set_cleanup(known_cipher_methods[i], -+ cipher_cleanup) -+ || !EVP_CIPHER_meth_set_impl_ctx_size(known_cipher_methods[i], -+ sizeof(struct cipher_ctx))) { -+ cipher_driver_info[i].status = DEVCRYPTO_STATUS_FAILURE; -+ EVP_CIPHER_meth_free(known_cipher_methods[i]); -+ known_cipher_methods[i] = NULL; -+ } else { -+ cipher_driver_info[i].status = DEVCRYPTO_STATUS_USABLE; -+#ifdef CIOCGSESSINFO -+ siop.ses = sess.ses; -+ if (ioctl(cfd, CIOCGSESSINFO, &siop) < 0) { -+ cipher_driver_info[i].accelerated = DEVCRYPTO_ACCELERATION_UNKNOWN; -+ } else { -+ cipher_driver_info[i].driver_name = -+ OPENSSL_strndup(siop.cipher_info.cra_driver_name, -+ CRYPTODEV_MAX_ALG_NAME); -+ if (!(siop.flags & SIOP_FLAG_KERNEL_DRIVER_ONLY)) -+ cipher_driver_info[i].accelerated = DEVCRYPTO_NOT_ACCELERATED; -+ else -+ cipher_driver_info[i].accelerated = DEVCRYPTO_ACCELERATED; -+ } -+#endif /* CIOCGSESSINFO */ -+ } -+ ioctl(cfd, CIOCFSESSION, &sess.ses); -+ if (devcrypto_test_cipher(i)) { -+ known_cipher_nids[known_cipher_nids_amount++] = -+ cipher_data[i].nid; -+ } -+ } -+} -+ -+static void rebuild_known_cipher_nids(ENGINE *e) -+{ -+ size_t i; -+ -+ for (i = 0, known_cipher_nids_amount = 0; i < OSSL_NELEM(cipher_data); i++) { -+ if (devcrypto_test_cipher(i)) -+ known_cipher_nids[known_cipher_nids_amount++] = cipher_data[i].nid; -+ } -+ ENGINE_unregister_ciphers(e); -+ ENGINE_register_ciphers(e); -+} -+ -+static const EVP_CIPHER *get_cipher_method(int nid) -+{ -+ size_t i = get_cipher_data_index(nid); -+ -+ if (i == (size_t)-1) -+ return NULL; -+ return known_cipher_methods[i]; -+} -+ -+static int get_cipher_nids(const int **nids) -+{ -+ *nids = known_cipher_nids; -+ return known_cipher_nids_amount; -+} -+ -+static void destroy_cipher_method(int nid) -+{ -+ size_t i = get_cipher_data_index(nid); -+ -+ EVP_CIPHER_meth_free(known_cipher_methods[i]); -+ known_cipher_methods[i] = NULL; -+} -+ -+static void destroy_all_cipher_methods(void) -+{ -+ size_t i; -+ -+ for (i = 0; i < OSSL_NELEM(cipher_data); i++) { -+ destroy_cipher_method(cipher_data[i].nid); -+ OPENSSL_free(cipher_driver_info[i].driver_name); -+ cipher_driver_info[i].driver_name = NULL; -+ } -+} -+ -+static int devcrypto_ciphers(ENGINE *e, const EVP_CIPHER **cipher, -+ const int **nids, int nid) -+{ -+ if (cipher == NULL) -+ return get_cipher_nids(nids); -+ -+ *cipher = get_cipher_method(nid); -+ -+ return *cipher != NULL; -+} -+ -+static void devcrypto_select_all_ciphers(int *cipher_list) -+{ -+ size_t i; -+ -+ for (i = 0; i < OSSL_NELEM(cipher_data); i++) -+ cipher_list[i] = 1; -+} -+ -+static int cryptodev_select_cipher_cb(const char *str, int len, void *usr) -+{ -+ int *cipher_list = (int *)usr; -+ char *name; -+ const EVP_CIPHER *EVP; -+ size_t i; -+ -+ if (len == 0) -+ return 1; -+ if (usr == NULL || (name = OPENSSL_strndup(str, len)) == NULL) -+ return 0; -+ EVP = EVP_get_cipherbyname(name); -+ if (EVP == NULL) -+ fprintf(stderr, "devcrypto: unknown cipher %s\n", name); -+ else if ((i = find_cipher_data_index(EVP_CIPHER_nid(EVP))) != (size_t)-1) -+ cipher_list[i] = 1; -+ else -+ fprintf(stderr, "devcrypto: cipher %s not available\n", name); -+ OPENSSL_free(name); -+ return 1; -+} -+ -+static void dump_cipher_info(void) -+{ -+ size_t i; -+ const char *name; -+ -+ fprintf (stderr, "Information about ciphers supported by the /dev/crypto" -+ " engine:\n"); -+#ifndef CIOCGSESSINFO -+ fprintf(stderr, "CIOCGSESSINFO (session info call) unavailable\n"); -+#endif -+ for (i = 0; i < OSSL_NELEM(cipher_data); i++) { -+ name = OBJ_nid2sn(cipher_data[i].nid); -+ fprintf (stderr, "Cipher %s, NID=%d, /dev/crypto info: id=%d, ", -+ name ? name : "unknown", cipher_data[i].nid, -+ cipher_data[i].devcryptoid); -+ if (cipher_driver_info[i].status == DEVCRYPTO_STATUS_NO_CIOCGSESSION ) { -+ fprintf (stderr, "CIOCGSESSION (session open call) failed\n"); -+ continue; -+ } -+ fprintf (stderr, "driver=%s ", cipher_driver_info[i].driver_name ? -+ cipher_driver_info[i].driver_name : "unknown"); -+ if (cipher_driver_info[i].accelerated == DEVCRYPTO_ACCELERATED) -+ fprintf(stderr, "(hw accelerated)"); -+ else if (cipher_driver_info[i].accelerated == DEVCRYPTO_NOT_ACCELERATED) -+ fprintf(stderr, "(software)"); -+ else -+ fprintf(stderr, "(acceleration status unknown)"); -+ if (cipher_driver_info[i].status == DEVCRYPTO_STATUS_FAILURE) -+ fprintf (stderr, ". Cipher setup failed"); -+ fprintf(stderr, "\n"); -+ } -+ fprintf(stderr, "\n"); -+} -+ -+/* -+ * We only support digests if the cryptodev implementation supports multiple -+ * data updates and session copying. Otherwise, we would be forced to maintain -+ * a cache, which is perilous if there's a lot of data coming in (if someone -+ * wants to checksum an OpenSSL tarball, for example). -+ */ -+#if defined(CIOCCPHASH) && defined(COP_FLAG_UPDATE) && defined(COP_FLAG_FINAL) -+#define IMPLEMENT_DIGEST -+ -+/****************************************************************************** -+ * -+ * Digests -+ * -+ * Because they all do the same basic operation, we have only one set of -+ * method functions for them all to share, and a mapping table between -+ * NIDs and cryptodev IDs, with all the necessary size data. -+ * -+ *****/ -+ -+struct digest_ctx { -+ struct session_op sess; -+ /* This signals that the init function was called, not that it succeeded. */ -+ int init_called; -+ unsigned char digest_res[HASH_MAX_LEN]; -+}; -+ -+static const struct digest_data_st { -+ int nid; -+ int blocksize; -+ int digestlen; -+ int devcryptoid; -+} digest_data[] = { -+#ifndef OPENSSL_NO_MD5 -+ { NID_md5, /* MD5_CBLOCK */ 64, 16, CRYPTO_MD5 }, -+#endif -+ { NID_sha1, SHA_CBLOCK, 20, CRYPTO_SHA1 }, -+#ifndef OPENSSL_NO_RMD160 -+# if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_RIPEMD160) -+ { NID_ripemd160, /* RIPEMD160_CBLOCK */ 64, 20, CRYPTO_RIPEMD160 }, -+# endif -+#endif -+#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_224) -+ { NID_sha224, SHA256_CBLOCK, 224 / 8, CRYPTO_SHA2_224 }, -+#endif -+#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_256) -+ { NID_sha256, SHA256_CBLOCK, 256 / 8, CRYPTO_SHA2_256 }, -+#endif -+#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_384) -+ { NID_sha384, SHA512_CBLOCK, 384 / 8, CRYPTO_SHA2_384 }, -+#endif -+#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_512) -+ { NID_sha512, SHA512_CBLOCK, 512 / 8, CRYPTO_SHA2_512 }, -+#endif -+}; -+ -+static size_t find_digest_data_index(int nid) -+{ -+ size_t i; -+ -+ for (i = 0; i < OSSL_NELEM(digest_data); i++) -+ if (nid == digest_data[i].nid) -+ return i; -+ return (size_t)-1; -+} -+ -+static size_t get_digest_data_index(int nid) -+{ -+ size_t i = find_digest_data_index(nid); -+ -+ if (i != (size_t)-1) -+ return i; -+ -+ /* -+ * Code further down must make sure that only NIDs in the table above -+ * are used. If any other NID reaches this function, there's a grave -+ * coding error further down. -+ */ -+ assert("Code that never should be reached" == NULL); -+ return -1; -+} -+ -+static const struct digest_data_st *get_digest_data(int nid) -+{ -+ return &digest_data[get_digest_data_index(nid)]; -+} -+ -+/* -+ * Following are the five necessary functions to map OpenSSL functionality -+ * with cryptodev: init, update, final, cleanup, and copy. -+ */ -+ -+static int digest_init(EVP_MD_CTX *ctx) -+{ -+ struct digest_ctx *digest_ctx = -+ (struct digest_ctx *)EVP_MD_CTX_md_data(ctx); -+ const struct digest_data_st *digest_d = -+ get_digest_data(EVP_MD_CTX_type(ctx)); -+ -+ digest_ctx->init_called = 1; -+ -+ memset(&digest_ctx->sess, 0, sizeof(digest_ctx->sess)); -+ digest_ctx->sess.mac = digest_d->devcryptoid; -+ if (ioctl(cfd, CIOCGSESSION, &digest_ctx->sess) < 0) { -+ SYSerr(SYS_F_IOCTL, errno); -+ return 0; -+ } -+ return 1; -+} -+ -+static int digest_op(struct digest_ctx *ctx, const void *src, size_t srclen, -+ void *res, unsigned int flags) -+{ -+ struct crypt_op cryp; -+ -+ memset(&cryp, 0, sizeof(cryp)); -+ cryp.ses = ctx->sess.ses; -+ cryp.len = srclen; -+ cryp.src = (void *)src; -+ cryp.dst = NULL; -+ cryp.mac = res; -+ cryp.flags = flags; -+ return ioctl(cfd, CIOCCRYPT, &cryp); -+} -+ -+static int digest_update(EVP_MD_CTX *ctx, const void *data, size_t count) -+{ -+ struct digest_ctx *digest_ctx = -+ (struct digest_ctx *)EVP_MD_CTX_md_data(ctx); -+ -+ if (count == 0) -+ return 1; -+ -+ if (digest_ctx == NULL) -+ return 0; -+ -+ if (EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_ONESHOT)) { -+ if (digest_op(digest_ctx, data, count, digest_ctx->digest_res, 0) >= 0) -+ return 1; -+ } else if (digest_op(digest_ctx, data, count, NULL, COP_FLAG_UPDATE) >= 0) { -+ return 1; -+ } -+ -+ SYSerr(SYS_F_IOCTL, errno); -+ return 0; -+} -+ -+static int digest_final(EVP_MD_CTX *ctx, unsigned char *md) -+{ -+ struct digest_ctx *digest_ctx = -+ (struct digest_ctx *)EVP_MD_CTX_md_data(ctx); -+ -+ if (md == NULL || digest_ctx == NULL) -+ return 0; -+ -+ if (EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_ONESHOT)) { -+ memcpy(md, digest_ctx->digest_res, EVP_MD_CTX_size(ctx)); -+ } else if (digest_op(digest_ctx, NULL, 0, md, COP_FLAG_FINAL) < 0) { -+ SYSerr(SYS_F_IOCTL, errno); -+ return 0; -+ } -+ -+ return 1; -+} -+ -+static int digest_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from) -+{ -+ struct digest_ctx *digest_from = -+ (struct digest_ctx *)EVP_MD_CTX_md_data(from); -+ struct digest_ctx *digest_to = -+ (struct digest_ctx *)EVP_MD_CTX_md_data(to); -+ struct cphash_op cphash; -+ -+ if (digest_from == NULL || digest_from->init_called != 1) -+ return 1; -+ -+ if (!digest_init(to)) { -+ SYSerr(SYS_F_IOCTL, errno); -+ return 0; -+ } -+ -+ cphash.src_ses = digest_from->sess.ses; -+ cphash.dst_ses = digest_to->sess.ses; -+ if (ioctl(cfd, CIOCCPHASH, &cphash) < 0) { -+ SYSerr(SYS_F_IOCTL, errno); -+ return 0; -+ } -+ return 1; -+} -+ -+static int digest_cleanup(EVP_MD_CTX *ctx) -+{ -+ struct digest_ctx *digest_ctx = -+ (struct digest_ctx *)EVP_MD_CTX_md_data(ctx); -+ -+ if (digest_ctx == NULL) -+ return 1; -+ -+ return clean_devcrypto_session(&digest_ctx->sess); -+} -+ -+/* -+ * Keep tables of known nids, associated methods, selected digests, and -+ * driver info. -+ * Note that known_digest_nids[] isn't necessarily indexed the same way as -+ * digest_data[] above, which the other tables are. -+ */ -+static int known_digest_nids[OSSL_NELEM(digest_data)]; -+static int known_digest_nids_amount = -1; /* -1 indicates not yet initialised */ -+static EVP_MD *known_digest_methods[OSSL_NELEM(digest_data)] = { NULL, }; -+static int selected_digests[OSSL_NELEM(digest_data)]; -+static struct driver_info_st digest_driver_info[OSSL_NELEM(digest_data)]; -+ -+static int devcrypto_test_digest(size_t digest_data_index) -+{ -+ return (digest_driver_info[digest_data_index].status == DEVCRYPTO_STATUS_USABLE -+ && selected_digests[digest_data_index] == 1 -+ && (digest_driver_info[digest_data_index].accelerated -+ == DEVCRYPTO_ACCELERATED -+ || use_softdrivers == DEVCRYPTO_USE_SOFTWARE -+ || (digest_driver_info[digest_data_index].accelerated -+ != DEVCRYPTO_NOT_ACCELERATED -+ && use_softdrivers == DEVCRYPTO_REJECT_SOFTWARE))); -+} -+ -+static void rebuild_known_digest_nids(ENGINE *e) -+{ -+ size_t i; -+ -+ for (i = 0, known_digest_nids_amount = 0; i < OSSL_NELEM(digest_data); i++) { -+ if (devcrypto_test_digest(i)) -+ known_digest_nids[known_digest_nids_amount++] = digest_data[i].nid; -+ } -+ ENGINE_unregister_digests(e); -+ ENGINE_register_digests(e); -+} -+ -+static void prepare_digest_methods(void) -+{ -+ size_t i; -+ struct session_op sess1, sess2; -+#ifdef CIOCGSESSINFO -+ struct session_info_op siop; -+#endif -+ struct cphash_op cphash; -+ -+ memset(&digest_driver_info, 0, sizeof(digest_driver_info)); -+ -+ memset(&sess1, 0, sizeof(sess1)); -+ memset(&sess2, 0, sizeof(sess2)); -+ -+ for (i = 0, known_digest_nids_amount = 0; i < OSSL_NELEM(digest_data); -+ i++) { -+ -+ selected_digests[i] = 1; -+ -+ /* -+ * Check that the digest is usable -+ */ -+ sess1.mac = digest_data[i].devcryptoid; -+ sess2.ses = 0; -+ if (ioctl(cfd, CIOCGSESSION, &sess1) < 0) { -+ digest_driver_info[i].status = DEVCRYPTO_STATUS_NO_CIOCGSESSION; -+ goto finish; -+ } -+ -+#ifdef CIOCGSESSINFO -+ /* gather hardware acceleration info from the driver */ -+ siop.ses = sess1.ses; -+ if (ioctl(cfd, CIOCGSESSINFO, &siop) < 0) { -+ digest_driver_info[i].accelerated = DEVCRYPTO_ACCELERATION_UNKNOWN; -+ } else { -+ digest_driver_info[i].driver_name = -+ OPENSSL_strndup(siop.hash_info.cra_driver_name, -+ CRYPTODEV_MAX_ALG_NAME); -+ if (siop.flags & SIOP_FLAG_KERNEL_DRIVER_ONLY) -+ digest_driver_info[i].accelerated = DEVCRYPTO_ACCELERATED; -+ else -+ digest_driver_info[i].accelerated = DEVCRYPTO_NOT_ACCELERATED; -+ } -+#endif -+ -+ /* digest must be capable of hash state copy */ -+ sess2.mac = sess1.mac; -+ if (ioctl(cfd, CIOCGSESSION, &sess2) < 0) { -+ digest_driver_info[i].status = DEVCRYPTO_STATUS_FAILURE; -+ goto finish; -+ } -+ cphash.src_ses = sess1.ses; -+ cphash.dst_ses = sess2.ses; -+ if (ioctl(cfd, CIOCCPHASH, &cphash) < 0) { -+ digest_driver_info[i].status = DEVCRYPTO_STATUS_NO_CIOCCPHASH; -+ goto finish; -+ } -+ if ((known_digest_methods[i] = EVP_MD_meth_new(digest_data[i].nid, -+ NID_undef)) == NULL -+ || !EVP_MD_meth_set_input_blocksize(known_digest_methods[i], -+ digest_data[i].blocksize) -+ || !EVP_MD_meth_set_result_size(known_digest_methods[i], -+ digest_data[i].digestlen) -+ || !EVP_MD_meth_set_init(known_digest_methods[i], digest_init) -+ || !EVP_MD_meth_set_update(known_digest_methods[i], digest_update) -+ || !EVP_MD_meth_set_final(known_digest_methods[i], digest_final) -+ || !EVP_MD_meth_set_copy(known_digest_methods[i], digest_copy) -+ || !EVP_MD_meth_set_cleanup(known_digest_methods[i], digest_cleanup) -+ || !EVP_MD_meth_set_app_datasize(known_digest_methods[i], -+ sizeof(struct digest_ctx))) { -+ digest_driver_info[i].status = DEVCRYPTO_STATUS_FAILURE; -+ EVP_MD_meth_free(known_digest_methods[i]); -+ known_digest_methods[i] = NULL; -+ goto finish; -+ } -+ digest_driver_info[i].status = DEVCRYPTO_STATUS_USABLE; -+finish: -+ ioctl(cfd, CIOCFSESSION, &sess1.ses); -+ if (sess2.ses != 0) -+ ioctl(cfd, CIOCFSESSION, &sess2.ses); -+ if (devcrypto_test_digest(i)) -+ known_digest_nids[known_digest_nids_amount++] = digest_data[i].nid; -+ } -+} -+ -+static const EVP_MD *get_digest_method(int nid) -+{ -+ size_t i = get_digest_data_index(nid); -+ -+ if (i == (size_t)-1) -+ return NULL; -+ return known_digest_methods[i]; -+} -+ -+static int get_digest_nids(const int **nids) -+{ -+ *nids = known_digest_nids; -+ return known_digest_nids_amount; -+} -+ -+static void destroy_digest_method(int nid) -+{ -+ size_t i = get_digest_data_index(nid); -+ -+ EVP_MD_meth_free(known_digest_methods[i]); -+ known_digest_methods[i] = NULL; -+} -+ -+static void destroy_all_digest_methods(void) -+{ -+ size_t i; -+ -+ for (i = 0; i < OSSL_NELEM(digest_data); i++) { -+ destroy_digest_method(digest_data[i].nid); -+ OPENSSL_free(digest_driver_info[i].driver_name); -+ digest_driver_info[i].driver_name = NULL; -+ } -+} -+ -+static int devcrypto_digests(ENGINE *e, const EVP_MD **digest, -+ const int **nids, int nid) -+{ -+ if (digest == NULL) -+ return get_digest_nids(nids); -+ -+ *digest = get_digest_method(nid); -+ -+ return *digest != NULL; -+} -+ -+static void devcrypto_select_all_digests(int *digest_list) -+{ -+ size_t i; -+ -+ for (i = 0; i < OSSL_NELEM(digest_data); i++) -+ digest_list[i] = 1; -+} -+ -+static int cryptodev_select_digest_cb(const char *str, int len, void *usr) -+{ -+ int *digest_list = (int *)usr; -+ char *name; -+ const EVP_MD *EVP; -+ size_t i; -+ -+ if (len == 0) -+ return 1; -+ if (usr == NULL || (name = OPENSSL_strndup(str, len)) == NULL) -+ return 0; -+ EVP = EVP_get_digestbyname(name); -+ if (EVP == NULL) -+ fprintf(stderr, "devcrypto: unknown digest %s\n", name); -+ else if ((i = find_digest_data_index(EVP_MD_type(EVP))) != (size_t)-1) -+ digest_list[i] = 1; -+ else -+ fprintf(stderr, "devcrypto: digest %s not available\n", name); -+ OPENSSL_free(name); -+ return 1; -+} -+ -+static void dump_digest_info(void) -+{ -+ size_t i; -+ const char *name; -+ -+ fprintf (stderr, "Information about digests supported by the /dev/crypto" -+ " engine:\n"); -+#ifndef CIOCGSESSINFO -+ fprintf(stderr, "CIOCGSESSINFO (session info call) unavailable\n"); -+#endif -+ -+ for (i = 0; i < OSSL_NELEM(digest_data); i++) { -+ name = OBJ_nid2sn(digest_data[i].nid); -+ fprintf (stderr, "Digest %s, NID=%d, /dev/crypto info: id=%d, driver=%s", -+ name ? name : "unknown", digest_data[i].nid, -+ digest_data[i].devcryptoid, -+ digest_driver_info[i].driver_name ? digest_driver_info[i].driver_name : "unknown"); -+ if (digest_driver_info[i].status == DEVCRYPTO_STATUS_NO_CIOCGSESSION) { -+ fprintf (stderr, ". CIOCGSESSION (session open) failed\n"); -+ continue; -+ } -+ if (digest_driver_info[i].accelerated == DEVCRYPTO_ACCELERATED) -+ fprintf(stderr, " (hw accelerated)"); -+ else if (digest_driver_info[i].accelerated == DEVCRYPTO_NOT_ACCELERATED) -+ fprintf(stderr, " (software)"); -+ else -+ fprintf(stderr, " (acceleration status unknown)"); -+ if (cipher_driver_info[i].status == DEVCRYPTO_STATUS_FAILURE) -+ fprintf (stderr, ". Cipher setup failed\n"); -+ else if (digest_driver_info[i].status == DEVCRYPTO_STATUS_NO_CIOCCPHASH) -+ fprintf(stderr, ", CIOCCPHASH failed\n"); -+ else -+ fprintf(stderr, ", CIOCCPHASH capable\n"); -+ } -+ fprintf(stderr, "\n"); -+} -+ -+#endif -+ -+/****************************************************************************** -+ * -+ * CONTROL COMMANDS -+ * -+ *****/ -+ -+#define DEVCRYPTO_CMD_USE_SOFTDRIVERS ENGINE_CMD_BASE -+#define DEVCRYPTO_CMD_CIPHERS (ENGINE_CMD_BASE + 1) -+#define DEVCRYPTO_CMD_DIGESTS (ENGINE_CMD_BASE + 2) -+#define DEVCRYPTO_CMD_DUMP_INFO (ENGINE_CMD_BASE + 3) -+ -+/* Helper macros for CPP string composition */ -+#ifndef OPENSSL_MSTR -+# define OPENSSL_MSTR_HELPER(x) #x -+# define OPENSSL_MSTR(x) OPENSSL_MSTR_HELPER(x) -+#endif -+ -+static const ENGINE_CMD_DEFN devcrypto_cmds[] = { -+#ifdef CIOCGSESSINFO -+ {DEVCRYPTO_CMD_USE_SOFTDRIVERS, -+ "USE_SOFTDRIVERS", -+ "specifies whether to use software (not accelerated) drivers (" -+ OPENSSL_MSTR(DEVCRYPTO_REQUIRE_ACCELERATED) "=use only accelerated drivers, " -+ OPENSSL_MSTR(DEVCRYPTO_USE_SOFTWARE) "=allow all drivers, " -+ OPENSSL_MSTR(DEVCRYPTO_REJECT_SOFTWARE) -+ "=use if acceleration can't be determined) [default=" -+ OPENSSL_MSTR(DEVCRYPTO_DEFAULT_USE_SOFTDRIVERS) "]", -+ ENGINE_CMD_FLAG_NUMERIC}, -+#endif -+ -+ {DEVCRYPTO_CMD_CIPHERS, -+ "CIPHERS", -+ "either ALL, NONE, or a comma-separated list of ciphers to enable [default=ALL]", -+ ENGINE_CMD_FLAG_STRING}, -+ -+#ifdef IMPLEMENT_DIGEST -+ {DEVCRYPTO_CMD_DIGESTS, -+ "DIGESTS", -+ "either ALL, NONE, or a comma-separated list of digests to enable [default=ALL]", -+ ENGINE_CMD_FLAG_STRING}, -+#endif -+ -+ {DEVCRYPTO_CMD_DUMP_INFO, -+ "DUMP_INFO", -+ "dump info about each algorithm to stderr; use 'openssl engine -pre DUMP_INFO devcrypto'", -+ ENGINE_CMD_FLAG_NO_INPUT}, -+ -+ {0, NULL, NULL, 0} -+}; -+ -+static int devcrypto_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void)) -+{ -+ int *new_list; -+ switch (cmd) { -+#ifdef CIOCGSESSINFO -+ case DEVCRYPTO_CMD_USE_SOFTDRIVERS: -+ switch (i) { -+ case DEVCRYPTO_REQUIRE_ACCELERATED: -+ case DEVCRYPTO_USE_SOFTWARE: -+ case DEVCRYPTO_REJECT_SOFTWARE: -+ break; -+ default: -+ fprintf(stderr, "devcrypto: invalid value (%ld) for USE_SOFTDRIVERS\n", i); -+ return 0; -+ } -+ if (use_softdrivers == i) -+ return 1; -+ use_softdrivers = i; -+#ifdef IMPLEMENT_DIGEST -+ rebuild_known_digest_nids(e); -+#endif -+ rebuild_known_cipher_nids(e); -+ return 1; -+#endif /* CIOCGSESSINFO */ -+ -+ case DEVCRYPTO_CMD_CIPHERS: -+ if (p == NULL) -+ return 1; -+ if (strcasecmp((const char *)p, "ALL") == 0) { -+ devcrypto_select_all_ciphers(selected_ciphers); -+ } else if (strcasecmp((const char*)p, "NONE") == 0) { -+ memset(selected_ciphers, 0, sizeof(selected_ciphers)); -+ } else { -+ new_list=OPENSSL_zalloc(sizeof(selected_ciphers)); -+ if (!CONF_parse_list(p, ',', 1, cryptodev_select_cipher_cb, new_list)) { -+ OPENSSL_free(new_list); -+ return 0; -+ } -+ memcpy(selected_ciphers, new_list, sizeof(selected_ciphers)); -+ OPENSSL_free(new_list); -+ } -+ rebuild_known_cipher_nids(e); -+ return 1; -+ -+#ifdef IMPLEMENT_DIGEST -+ case DEVCRYPTO_CMD_DIGESTS: -+ if (p == NULL) -+ return 1; -+ if (strcasecmp((const char *)p, "ALL") == 0) { -+ devcrypto_select_all_digests(selected_digests); -+ } else if (strcasecmp((const char*)p, "NONE") == 0) { -+ memset(selected_digests, 0, sizeof(selected_digests)); -+ } else { -+ new_list=OPENSSL_zalloc(sizeof(selected_digests)); -+ if (!CONF_parse_list(p, ',', 1, cryptodev_select_digest_cb, new_list)) { -+ OPENSSL_free(new_list); -+ return 0; -+ } -+ memcpy(selected_digests, new_list, sizeof(selected_digests)); -+ OPENSSL_free(new_list); -+ } -+ rebuild_known_digest_nids(e); -+ return 1; -+#endif /* IMPLEMENT_DIGEST */ -+ -+ case DEVCRYPTO_CMD_DUMP_INFO: -+ dump_cipher_info(); -+#ifdef IMPLEMENT_DIGEST -+ dump_digest_info(); -+#endif -+ return 1; -+ -+ default: -+ break; -+ } -+ return 0; -+} -+ -+/****************************************************************************** -+ * -+ * LOAD / UNLOAD -+ * -+ *****/ -+ -+/* -+ * Opens /dev/crypto -+ */ -+static int open_devcrypto(void) -+{ -+ if (cfd >= 0) -+ return 1; -+ -+ if ((cfd = open("/dev/crypto", O_RDWR, 0)) < 0) { -+#ifndef ENGINE_DEVCRYPTO_DEBUG -+ if (errno != ENOENT) -+#endif -+ fprintf(stderr, "Could not open /dev/crypto: %s\n", strerror(errno)); -+ return 0; -+ } -+ + return 1; +} + @@ -2576,17 +237,20 @@ Signed-off-by: Eneas U de Queiroz + if (ret != 0) { + fprintf(stderr, "Error closing /dev/crypto: %s\n", strerror(errno)); + return 0; -+ } + } + return 1; +} -+ + +- prepare_cipher_methods(); +static int devcrypto_unload(ENGINE *e) +{ + destroy_all_cipher_methods(); -+#ifdef IMPLEMENT_DIGEST + #ifdef IMPLEMENT_DIGEST +- prepare_digest_methods(); + destroy_all_digest_methods(); -+#endif -+ + #endif + +- if (!ENGINE_set_id(e, "devcrypto") + close_devcrypto(); + + return 1; @@ -2595,12 +259,13 @@ Signed-off-by: Eneas U de Queiroz +static int bind_devcrypto(ENGINE *e) { + + if (!ENGINE_set_id(e, engine_devcrypto_id) -+ || !ENGINE_set_name(e, "/dev/crypto engine") + || !ENGINE_set_name(e, "/dev/crypto engine") + || !ENGINE_set_destroy_function(e, devcrypto_unload) -+ || !ENGINE_set_cmd_defns(e, devcrypto_cmds) + || !ENGINE_set_cmd_defns(e, devcrypto_cmds) +- || !ENGINE_set_ctrl_function(e, devcrypto_ctrl) + || !ENGINE_set_ctrl_function(e, devcrypto_ctrl)) + return 0; -+ + + prepare_cipher_methods(); +#ifdef IMPLEMENT_DIGEST + prepare_digest_methods(); @@ -2610,40 +275,34 @@ Signed-off-by: Eneas U de Queiroz +#ifdef IMPLEMENT_DIGEST + && ENGINE_set_digests(e, devcrypto_digests) +#endif -+/* -+ * Asymmetric ciphers aren't well supported with /dev/crypto. Among the BSD -+ * implementations, it seems to only exist in FreeBSD, and regarding the -+ * parameters in its crypt_kop, the manual crypto(4) has this to say: -+ * -+ * The semantics of these arguments are currently undocumented. -+ * -+ * Reading through the FreeBSD source code doesn't give much more than -+ * their CRK_MOD_EXP implementation for ubsec. -+ * -+ * It doesn't look much better with cryptodev-linux. They have the crypt_kop -+ * structure as well as the command (CRK_*) in cryptodev.h, but no support -+ * seems to be implemented at all for the moment. -+ * -+ * At the time of writing, it seems impossible to write proper support for -+ * FreeBSD's asym features without some very deep knowledge and access to -+ * specific kernel modules. -+ * -+ * /Richard Levitte, 2017-05-11 -+ */ -+#if 0 -+# ifndef OPENSSL_NO_RSA + /* + * Asymmetric ciphers aren't well supported with /dev/crypto. Among the BSD + * implementations, it seems to only exist in FreeBSD, and regarding the +@@ -1237,23 +1254,36 @@ void engine_load_devcrypto_int() + */ + #if 0 + # ifndef OPENSSL_NO_RSA +- || !ENGINE_set_RSA(e, devcrypto_rsa) + && ENGINE_set_RSA(e, devcrypto_rsa) -+# endif -+# ifndef OPENSSL_NO_DSA + # endif + # ifndef OPENSSL_NO_DSA +- || !ENGINE_set_DSA(e, devcrypto_dsa) + && ENGINE_set_DSA(e, devcrypto_dsa) -+# endif -+# ifndef OPENSSL_NO_DH + # endif + # ifndef OPENSSL_NO_DH +- || !ENGINE_set_DH(e, devcrypto_dh) + && ENGINE_set_DH(e, devcrypto_dh) -+# endif -+# ifndef OPENSSL_NO_EC + # endif + # ifndef OPENSSL_NO_EC +- || !ENGINE_set_EC(e, devcrypto_ec) + && ENGINE_set_EC(e, devcrypto_ec) -+# endif -+#endif + # endif + #endif +- || !ENGINE_set_ciphers(e, devcrypto_ciphers) +-#ifdef IMPLEMENT_DIGEST +- || !ENGINE_set_digests(e, devcrypto_digests) +-#endif +- ) { + ); +} + @@ -2662,14 +321,13 @@ Signed-off-by: Eneas U de Queiroz + if ((e = ENGINE_new()) == NULL + || !bind_devcrypto(e)) { + close_devcrypto(); -+ ENGINE_free(e); -+ return; -+ } -+ -+ ENGINE_add(e); -+ ENGINE_free(e); /* Loose our local reference */ -+ ERR_clear_error(); -+} + ENGINE_free(e); + return; + } +@@ -1262,3 +1292,22 @@ void engine_load_devcrypto_int() + ENGINE_free(e); /* Loose our local reference */ + ERR_clear_error(); + } + +#else + diff --git a/package/libs/openssl/patches/500-e_devcrypto-default-to-not-use-digests-in-engine.patch b/package/libs/openssl/patches/500-e_devcrypto-default-to-not-use-digests-in-engine.patch index df5c16d8d2..1f1cd7a582 100644 --- a/package/libs/openssl/patches/500-e_devcrypto-default-to-not-use-digests-in-engine.patch +++ b/package/libs/openssl/patches/500-e_devcrypto-default-to-not-use-digests-in-engine.patch @@ -19,6 +19,8 @@ turn them on if it is safe and fast enough. Signed-off-by: Eneas U de Queiroz +diff --git a/engines/e_devcrypto.c b/engines/e_devcrypto.c +index 3fcd81de7a..d25230d366 100644 --- a/engines/e_devcrypto.c +++ b/engines/e_devcrypto.c @@ -852,7 +852,7 @@ static void prepare_digest_methods(void) @@ -30,7 +32,7 @@ Signed-off-by: Eneas U de Queiroz /* * Check that the digest is usable -@@ -1072,7 +1072,7 @@ static const ENGINE_CMD_DEFN devcrypto_c +@@ -1072,7 +1072,7 @@ static const ENGINE_CMD_DEFN devcrypto_cmds[] = { #ifdef IMPLEMENT_DIGEST {DEVCRYPTO_CMD_DIGESTS, "DIGESTS", diff --git a/package/libs/openssl/patches/510-e_devcrypto-ignore-error-when-closing-session.patch b/package/libs/openssl/patches/510-e_devcrypto-ignore-error-when-closing-session.patch index 87792cf9d0..bc514b88c9 100644 --- a/package/libs/openssl/patches/510-e_devcrypto-ignore-error-when-closing-session.patch +++ b/package/libs/openssl/patches/510-e_devcrypto-ignore-error-when-closing-session.patch @@ -8,9 +8,11 @@ session. It may have been closed by another process after a fork. Signed-off-by: Eneas U de Queiroz +diff --git a/engines/e_devcrypto.c b/engines/e_devcrypto.c +index d25230d366..f4570f1666 100644 --- a/engines/e_devcrypto.c +++ b/engines/e_devcrypto.c -@@ -195,9 +195,8 @@ static int cipher_init(EVP_CIPHER_CTX *c +@@ -195,9 +195,8 @@ static int cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, get_cipher_data(EVP_CIPHER_CTX_nid(ctx)); /* cleanup a previous session */