summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.azure-pipelines.yml10
-rw-r--r--.github/pull_request_template.md3
-rw-r--r--.gitlab-ci.yml10
-rw-r--r--arch/arm/dts/k3-am65-mcu.dtsi128
-rw-r--r--arch/arm/dts/k3-am654-base-board-u-boot.dtsi155
-rw-r--r--arch/arm/dts/k3-j721e-common-proc-board-u-boot.dtsi174
-rw-r--r--arch/arm/dts/k3-j721e-mcu-wakeup.dtsi117
-rw-r--r--arch/arm/mach-k3/common.c2
-rw-r--r--arch/arm/mach-k3/config.mk17
-rw-r--r--board/davinci/da8xxevm/da850evm.c6
-rw-r--r--board/ti/beagle/beagle.c70
-rw-r--r--cmd/nvedit_efi.c24
-rw-r--r--configs/da850evm_direct_nor_defconfig1
-rw-r--r--configs/omap3_beagle_defconfig3
-rw-r--r--doc/README.davinci10
-rw-r--r--doc/api/efi.rst2
-rw-r--r--drivers/dma/ti/Kconfig4
-rw-r--r--drivers/dma/ti/Makefile4
-rw-r--r--drivers/dma/ti/k3-psil-am654.c89
-rw-r--r--drivers/dma/ti/k3-psil-j721e.c47
-rw-r--r--drivers/dma/ti/k3-psil-priv.h43
-rw-r--r--drivers/dma/ti/k3-psil.c42
-rw-r--r--drivers/dma/ti/k3-psil.h67
-rw-r--r--drivers/dma/ti/k3-udma.c402
-rw-r--r--drivers/mmc/omap_hsmmc.c2
-rw-r--r--drivers/net/ti/am65-cpsw-nuss.c15
-rw-r--r--drivers/soc/ti/k3-navss-ringacc.c161
-rw-r--r--fs/fat/fat_write.c9
-rw-r--r--include/configs/da850evm.h23
-rw-r--r--include/crypto/pkcs7_parser.h2
-rw-r--r--include/dt-bindings/dma/k3-udma.h31
-rw-r--r--include/efi_api.h2
-rw-r--r--include/efi_loader.h21
-rw-r--r--include/efi_variable.h198
-rw-r--r--include/linux/soc/ti/k3-navss-ringacc.h4
-rw-r--r--include/u-boot/rsa.h3
-rw-r--r--lib/efi_loader/Kconfig8
-rw-r--r--lib/efi_loader/Makefile3
-rw-r--r--lib/efi_loader/efi_bootmgr.c28
-rw-r--r--lib/efi_loader/efi_boottime.c12
-rw-r--r--lib/efi_loader/efi_image_loader.c164
-rw-r--r--lib/efi_loader/efi_runtime.c38
-rw-r--r--lib/efi_loader/efi_setup.c59
-rw-r--r--lib/efi_loader/efi_signature.c435
-rw-r--r--lib/efi_loader/efi_var_common.c140
-rw-r--r--lib/efi_loader/efi_var_file.c239
-rw-r--r--lib/efi_loader/efi_var_mem.c266
-rw-r--r--lib/efi_loader/efi_variable.c836
-rw-r--r--lib/efi_loader/efi_variable_tee.c138
-rw-r--r--lib/efi_selftest/efi_selftest_variables_runtime.c13
-rw-r--r--lib/rsa/rsa-verify.c8
-rw-r--r--scripts/config_whitelist.txt2
-rw-r--r--test/py/tests/test_efi_secboot/conftest.py121
-rw-r--r--test/py/tests/test_efi_secboot/defs.py15
-rw-r--r--test/py/tests/test_efi_secboot/test_authvar.py92
-rw-r--r--test/py/tests/test_efi_secboot/test_signed.py206
-rw-r--r--test/py/tests/test_efi_secboot/test_unsigned.py66
57 files changed, 2808 insertions, 1982 deletions
diff --git a/.azure-pipelines.yml b/.azure-pipelines.yml
index 98e8a4fe142..97c89fc0671 100644
--- a/.azure-pipelines.yml
+++ b/.azure-pipelines.yml
@@ -294,10 +294,6 @@ jobs:
ln -s travis-ci /tmp/uboot-test-hooks/py/`hostname`
grub-mkimage --prefix=\"\" -o ~/grub_x86.efi -O i386-efi normal echo lsefimmap lsefi lsefisystab efinet tftp minicmd
grub-mkimage --prefix=\"\" -o ~/grub_x64.efi -O x86_64-efi normal echo lsefimmap lsefi lsefisystab efinet tftp minicmd
- cp /opt/grub/grubriscv64.efi ~/grub_riscv64.efi
- cp /opt/grub/grubriscv32.efi ~/grub_riscv32.efi
- cp /opt/grub/grubaa64.efi ~/grub_arm64.efi
- cp /opt/grub/grubarm.efi ~/grub_arm.efi
if [[ "${TEST_PY_BD}" == "qemu-riscv32_spl" ]]; then
wget -O - https://github.com/riscv/opensbi/releases/download/v0.6/opensbi-0.6-rv32-bin.tar.xz | tar -C /tmp -xJ;
export OPENSBI=/tmp/opensbi-0.6-rv32-bin/platform/qemu/virt/firmware/fw_dynamic.bin;
@@ -310,6 +306,12 @@ jobs:
cd ${WORK_DIR}
export UBOOT_TRAVIS_BUILD_DIR=/tmp/${TEST_PY_BD};
tools/buildman/buildman -o ${UBOOT_TRAVIS_BUILD_DIR} -w -E -W -e --board ${TEST_PY_BD} ${OVERRIDE}
+ cp ~/grub_x86.efi ${UBOOT_TRAVIS_BUILD_DIR}/
+ cp ~/grub_x64.efi ${UBOOT_TRAVIS_BUILD_DIR}/
+ cp /opt/grub/grubriscv64.efi ${UBOOT_TRAVIS_BUILD_DIR}/grub_riscv64.efi
+ cp /opt/grub/grubriscv32.efi ${UBOOT_TRAVIS_BUILD_DIR}/grub_riscv32.efi
+ cp /opt/grub/grubaa64.efi ${UBOOT_TRAVIS_BUILD_DIR}/grub_arm64.efi
+ cp /opt/grub/grubarm.efi ${UBOOT_TRAVIS_BUILD_DIR}/grub_arm.efi
virtualenv -p /usr/bin/python3 /tmp/venv
. /tmp/venv/bin/activate
pip install -r test/py/requirements.txt
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
index 23599b97c0e..ae91252a00b 100644
--- a/.github/pull_request_template.md
+++ b/.github/pull_request_template.md
@@ -1,3 +1,6 @@
Please do not submit a Pull Request via github. Our project makes use of
mailing lists for patch submission and review. For more details please
see https://www.denx.de/wiki/U-Boot/Patches
+
+The only exception to this is in order to trigger a CI loop on Azure prior
+to posting of patches.
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index d0746955b44..d2f864669d8 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -20,10 +20,6 @@ stages:
- ln -s travis-ci /tmp/uboot-test-hooks/py/`hostname`
- grub-mkimage --prefix="" -o ~/grub_x86.efi -O i386-efi normal echo lsefimmap lsefi lsefisystab efinet tftp minicmd
- grub-mkimage --prefix="" -o ~/grub_x64.efi -O x86_64-efi normal echo lsefimmap lsefi lsefisystab efinet tftp minicmd
- - cp /opt/grub/grubriscv64.efi ~/grub_riscv64.efi
- - cp /opt/grub/grubriscv32.efi ~/grub_riscv32.efi
- - cp /opt/grub/grubaa64.efi ~/grub_arm64.efi
- - cp /opt/grub/grubarm.efi ~/grub_arm.efi
- if [[ "${TEST_PY_BD}" == "qemu-riscv32_spl" ]]; then
wget -O - https://github.com/riscv/opensbi/releases/download/v0.6/opensbi-0.6-rv32-bin.tar.xz | tar -C /tmp -xJ;
export OPENSBI=/tmp/opensbi-0.6-rv32-bin/platform/qemu/virt/firmware/fw_dynamic.bin;
@@ -40,6 +36,12 @@ stages:
- export UBOOT_TRAVIS_BUILD_DIR=/tmp/${TEST_PY_BD}
- tools/buildman/buildman -o ${UBOOT_TRAVIS_BUILD_DIR} -w -E -W -e
--board ${TEST_PY_BD} ${OVERRIDE}
+ - cp ~/grub_x86.efi $UBOOT_TRAVIS_BUILD_DIR/
+ - cp ~/grub_x64.efi $UBOOT_TRAVIS_BUILD_DIR/
+ - cp /opt/grub/grubriscv64.efi $UBOOT_TRAVIS_BUILD_DIR/grub_riscv64.efi
+ - cp /opt/grub/grubriscv32.efi $UBOOT_TRAVIS_BUILD_DIR/grub_riscv32.efi
+ - cp /opt/grub/grubaa64.efi $UBOOT_TRAVIS_BUILD_DIR/grub_arm64.efi
+ - cp /opt/grub/grubarm.efi $UBOOT_TRAVIS_BUILD_DIR/grub_arm.efi
- virtualenv -p /usr/bin/python3 /tmp/venv
- . /tmp/venv/bin/activate
- pip install -r test/py/requirements.txt
diff --git a/arch/arm/dts/k3-am65-mcu.dtsi b/arch/arm/dts/k3-am65-mcu.dtsi
index bc9a87210da..13556858392 100644
--- a/arch/arm/dts/k3-am65-mcu.dtsi
+++ b/arch/arm/dts/k3-am65-mcu.dtsi
@@ -6,6 +6,20 @@
*/
&cbass_mcu {
+ mcu_conf: scm_conf@40f00000 {
+ compatible = "syscon", "simple-mfd";
+ reg = <0x0 0x40f00000 0x0 0x20000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x0 0x0 0x40f00000 0x20000>;
+
+ phy_gmii_sel: phy@4040 {
+ compatible = "ti,am654-phy-gmii-sel";
+ reg = <0x4040 0x4>;
+ #phy-cells = <1>;
+ };
+ };
+
mcu_uart0: serial@40a00000 {
compatible = "ti,am654-uart";
reg = <0x00 0x40a00000 0x00 0x100>;
@@ -102,4 +116,118 @@
#size-cells = <0>;
};
};
+
+ mcu_navss {
+ compatible = "simple-mfd";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+ dma-coherent;
+ dma-ranges;
+
+ ti,sci-dev-id = <119>;
+
+ mcu_ringacc: ringacc@2b800000 {
+ compatible = "ti,am654-navss-ringacc";
+ reg = <0x0 0x2b800000 0x0 0x400000>,
+ <0x0 0x2b000000 0x0 0x400000>,
+ <0x0 0x28590000 0x0 0x100>,
+ <0x0 0x2a500000 0x0 0x40000>;
+ reg-names = "rt", "fifos", "proxy_gcfg", "proxy_target";
+ ti,num-rings = <286>;
+ ti,sci-rm-range-gp-rings = <0x2>; /* GP ring range */
+ ti,dma-ring-reset-quirk;
+ ti,sci = <&dmsc>;
+ ti,sci-dev-id = <195>;
+ };
+
+ mcu_udmap: dma-controller@285c0000 {
+ compatible = "ti,am654-navss-mcu-udmap";
+ reg = <0x0 0x285c0000 0x0 0x100>,
+ <0x0 0x2a800000 0x0 0x40000>,
+ <0x0 0x2aa00000 0x0 0x40000>;
+ reg-names = "gcfg", "rchanrt", "tchanrt";
+ #dma-cells = <1>;
+
+ ti,sci = <&dmsc>;
+ ti,sci-dev-id = <194>;
+ ti,ringacc = <&mcu_ringacc>;
+
+ ti,sci-rm-range-tchan = <0x1>, /* TX_HCHAN */
+ <0x2>; /* TX_CHAN */
+ ti,sci-rm-range-rchan = <0x3>, /* RX_HCHAN */
+ <0x4>; /* RX_CHAN */
+ ti,sci-rm-range-rflow = <0x5>; /* GP RFLOW */
+ };
+ };
+
+ mcu_cpsw: ethernet@46000000 {
+ compatible = "ti,am654-cpsw-nuss";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ reg = <0x0 0x46000000 0x0 0x200000>;
+ reg-names = "cpsw_nuss";
+ ranges = <0x0 0x0 0x0 0x46000000 0x0 0x200000>;
+ dma-coherent;
+ clocks = <&k3_clks 5 10>;
+ clock-names = "fck";
+ power-domains = <&k3_pds 5 TI_SCI_PD_EXCLUSIVE>;
+
+ dmas = <&mcu_udmap 0xf000>,
+ <&mcu_udmap 0xf001>,
+ <&mcu_udmap 0xf002>,
+ <&mcu_udmap 0xf003>,
+ <&mcu_udmap 0xf004>,
+ <&mcu_udmap 0xf005>,
+ <&mcu_udmap 0xf006>,
+ <&mcu_udmap 0xf007>,
+ <&mcu_udmap 0x7000>;
+ dma-names = "tx0", "tx1", "tx2", "tx3",
+ "tx4", "tx5", "tx6", "tx7",
+ "rx";
+
+ ethernet-ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpsw_port1: port@1 {
+ reg = <1>;
+ ti,mac-only;
+ label = "port1";
+ ti,syscon-efuse = <&mcu_conf 0x200>;
+ phys = <&phy_gmii_sel 1>;
+ };
+ };
+
+ davinci_mdio: mdio@f00 {
+ compatible = "ti,cpsw-mdio","ti,davinci_mdio";
+ reg = <0x0 0xf00 0x0 0x100>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clocks = <&k3_clks 5 10>;
+ clock-names = "fck";
+ bus_freq = <1000000>;
+ };
+
+ cpts@3d000 {
+ compatible = "ti,am65-cpts";
+ reg = <0x0 0x3d000 0x0 0x400>;
+ clocks = <&mcu_cpsw_cpts_mux>;
+ clock-names = "cpts";
+ interrupts-extended = <&gic500 GIC_SPI 570 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "cpts";
+ ti,cpts-ext-ts-inputs = <4>;
+ ti,cpts-periodic-outputs = <2>;
+
+ mcu_cpsw_cpts_mux: refclk-mux {
+ #clock-cells = <0>;
+ clocks = <&k3_clks 118 5>, <&k3_clks 118 11>,
+ <&k3_clks 118 6>, <&k3_clks 118 3>,
+ <&k3_clks 118 8>, <&k3_clks 118 14>,
+ <&k3_clks 120 3>, <&k3_clks 121 3>;
+ assigned-clocks = <&mcu_cpsw_cpts_mux>;
+ assigned-clock-parents = <&k3_clks 118 5>;
+ };
+ };
+ };
};
diff --git a/arch/arm/dts/k3-am654-base-board-u-boot.dtsi b/arch/arm/dts/k3-am654-base-board-u-boot.dtsi
index a7e5eb05531..d9ff3ed47b2 100644
--- a/arch/arm/dts/k3-am654-base-board-u-boot.dtsi
+++ b/arch/arm/dts/k3-am654-base-board-u-boot.dtsi
@@ -4,7 +4,6 @@
*/
#include <dt-bindings/pinctrl/k3.h>
-#include <dt-bindings/dma/k3-udma.h>
#include <dt-bindings/net/ti-dp83867.h>
/ {
@@ -47,164 +46,17 @@
&cbass_mcu {
u-boot,dm-spl;
- navss_mcu: navss-mcu {
- compatible = "simple-bus";
- #address-cells = <2>;
- #size-cells = <2>;
- ranges;
+ mcu_navss {
u-boot,dm-spl;
- ti,sci-dev-id = <119>;
-
- mcu_ringacc: ringacc@2b800000 {
- compatible = "ti,am654-navss-ringacc";
- reg = <0x0 0x2b800000 0x0 0x400000>,
- <0x0 0x2b000000 0x0 0x400000>,
- <0x0 0x28590000 0x0 0x100>,
- <0x0 0x2a500000 0x0 0x40000>;
- reg-names = "rt", "fifos",
- "proxy_gcfg", "proxy_target";
- ti,num-rings = <286>;
- ti,sci-rm-range-gp-rings = <0x2>; /* GP ring range */
- ti,dma-ring-reset-quirk;
- ti,sci = <&dmsc>;
- ti,sci-dev-id = <195>;
+ ringacc@2b800000 {
u-boot,dm-spl;
};
- mcu_udmap: udmap@285c0000 {
- compatible = "ti,k3-navss-udmap";
- reg = <0x0 0x285c0000 0x0 0x100>,
- <0x0 0x2a800000 0x0 0x40000>,
- <0x0 0x2aa00000 0x0 0x40000>;
- reg-names = "gcfg", "rchanrt", "tchanrt";
- #dma-cells = <3>;
-
- ti,ringacc = <&mcu_ringacc>;
- ti,psil-base = <0x6000>;
-
- ti,sci = <&dmsc>;
- ti,sci-dev-id = <194>;
-
- ti,sci-rm-range-tchan = <0x1>, /* TX_HCHAN */
- <0x2>; /* TX_CHAN */
- ti,sci-rm-range-rchan = <0x3>, /* RX_HCHAN */
- <0x4>; /* RX_CHAN */
- ti,sci-rm-range-rflow = <0x5>; /* GP RFLOW */
- dma-coherent;
+ dma-controller@285c0000 {
u-boot,dm-spl;
};
};
-
- mcu_conf: scm_conf@40f00000 {
- compatible = "syscon";
- reg = <0x0 0x40f00000 0x0 0x20000>;
- };
-
- mcu_cpsw: cpsw_nuss@046000000 {
- compatible = "ti,am654-cpsw-nuss";
- #address-cells = <2>;
- #size-cells = <2>;
- reg = <0x0 0x46000000 0x0 0x200000>;
- reg-names = "cpsw_nuss";
- ranges;
- dma-coherent;
- clocks = <&k3_clks 5 10>;
- clock-names = "fck";
- power-domains = <&k3_pds 5 TI_SCI_PD_EXCLUSIVE>;
- ti,psil-base = <0x7000>;
-
- dmas = <&mcu_udmap &mcu_cpsw 0 UDMA_DIR_TX>,
- <&mcu_udmap &mcu_cpsw 1 UDMA_DIR_TX>,
- <&mcu_udmap &mcu_cpsw 2 UDMA_DIR_TX>,
- <&mcu_udmap &mcu_cpsw 3 UDMA_DIR_TX>,
- <&mcu_udmap &mcu_cpsw 4 UDMA_DIR_TX>,
- <&mcu_udmap &mcu_cpsw 5 UDMA_DIR_TX>,
- <&mcu_udmap &mcu_cpsw 6 UDMA_DIR_TX>,
- <&mcu_udmap &mcu_cpsw 7 UDMA_DIR_TX>,
- <&mcu_udmap &mcu_cpsw 0 UDMA_DIR_RX>;
- dma-names = "tx0", "tx1", "tx2", "tx3",
- "tx4", "tx5", "tx6", "tx7",
- "rx";
-
- ports {
- #address-cells = <1>;
- #size-cells = <0>;
- host: host@0 {
- reg = <0>;
- ti,label = "host";
- };
-
- cpsw_port1: port@1 {
- reg = <1>;
- ti,mac-only;
- ti,label = "port1";
- ti,syscon-efuse = <&mcu_conf 0x200>;
- };
- };
-
- davinci_mdio: mdio {
- #address-cells = <1>;
- #size-cells = <0>;
- bus_freq = <1000000>;
- };
-
- ti,psil-config0 {
- linux,udma-mode = <UDMA_PKT_MODE>;
- statictr-type = <PSIL_STATIC_TR_NONE>;
- ti,needs-epib;
- ti,psd-size = <16>;
- };
-
- ti,psil-config1 {
- linux,udma-mode = <UDMA_PKT_MODE>;
- statictr-type = <PSIL_STATIC_TR_NONE>;
- ti,needs-epib;
- ti,psd-size = <16>;
- };
-
- ti,psil-config2 {
- linux,udma-mode = <UDMA_PKT_MODE>;
- statictr-type = <PSIL_STATIC_TR_NONE>;
- ti,needs-epib;
- ti,psd-size = <16>;
- };
-
- ti,psil-config3 {
- linux,udma-mode = <UDMA_PKT_MODE>;
- statictr-type = <PSIL_STATIC_TR_NONE>;
- ti,needs-epib;
- ti,psd-size = <16>;
- };
-
- ti,psil-config4 {
- linux,udma-mode = <UDMA_PKT_MODE>;
- statictr-type = <PSIL_STATIC_TR_NONE>;
- ti,needs-epib;
- ti,psd-size = <16>;
- };
-
- ti,psil-config5 {
- linux,udma-mode = <UDMA_PKT_MODE>;
- statictr-type = <PSIL_STATIC_TR_NONE>;
- ti,needs-epib;
- ti,psd-size = <16>;
- };
-
- ti,psil-config6 {
- linux,udma-mode = <UDMA_PKT_MODE>;
- statictr-type = <PSIL_STATIC_TR_NONE>;
- ti,needs-epib;
- ti,psd-size = <16>;
- };
-
- ti,psil-config7 {
- linux,udma-mode = <UDMA_PKT_MODE>;
- statictr-type = <PSIL_STATIC_TR_NONE>;
- ti,needs-epib;
- ti,psd-size = <16>;
- };
- };
};
&cbass_wakeup {
@@ -366,6 +218,7 @@
reg = <0x0 0x46000000 0x0 0x200000>,
<0x0 0x40f00200 0x0 0x2>;
reg-names = "cpsw_nuss", "mac_efuse";
+ /delete-property/ ranges;
cpsw-phy-sel@40f04040 {
compatible = "ti,am654-cpsw-phy-sel";
diff --git a/arch/arm/dts/k3-j721e-common-proc-board-u-boot.dtsi b/arch/arm/dts/k3-j721e-common-proc-board-u-boot.dtsi
index 7b01e4204f7..6e748bfebb6 100644
--- a/arch/arm/dts/k3-j721e-common-proc-board-u-boot.dtsi
+++ b/arch/arm/dts/k3-j721e-common-proc-board-u-boot.dtsi
@@ -3,7 +3,6 @@
* Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
*/
-#include <dt-bindings/dma/k3-udma.h>
#include <dt-bindings/net/ti-dp83867.h>
/ {
@@ -32,183 +31,17 @@
u-boot,dm-spl;
};
- mcu_conf: scm_conf@40f00000 {
- compatible = "syscon", "simple-mfd";
- reg = <0x0 0x40f00000 0x0 0x20000>;
- #address-cells = <1>;
- #size-cells = <1>;
- ranges = <0x0 0x0 0x40f00000 0x20000>;
-
- phy_sel: cpsw-phy-sel@4040 {
- compatible = "ti,am654-cpsw-phy-sel";
- reg = <0x4040 0x4>;
- reg-names = "gmii-sel";
- };
- };
-
- cbass_mcu_navss: mcu_navss {
- compatible = "simple-bus";
- #address-cells = <2>;
- #size-cells = <2>;
- dma-coherent;
- dma-ranges;
- ranges;
-
- ti,sci-dev-id = <232>;
+ mcu_navss {
u-boot,dm-spl;
- mcu_ringacc: ringacc@2b800000 {
- compatible = "ti,am654-navss-ringacc";
- reg = <0x0 0x2b800000 0x0 0x400000>,
- <0x0 0x2b000000 0x0 0x400000>,
- <0x0 0x28590000 0x0 0x100>,
- <0x0 0x2a500000 0x0 0x40000>;
- reg-names = "rt", "fifos", "proxy_gcfg", "proxy_target";
- ti,num-rings = <286>;
- ti,sci-rm-range-gp-rings = <0x1>; /* GP ring range */
- ti,sci = <&dmsc>;
- ti,sci-dev-id = <235>;
+ ringacc@2b800000 {
u-boot,dm-spl;
};
- mcu_udmap: udmap@31150000 {
- compatible = "ti,j721e-navss-mcu-udmap";
- reg = <0x0 0x285c0000 0x0 0x100>,
- <0x0 0x2a800000 0x0 0x40000>,
- <0x0 0x2aa00000 0x0 0x40000>;
- reg-names = "gcfg", "rchanrt", "tchanrt";
- #dma-cells = <3>;
-
- ti,ringacc = <&mcu_ringacc>;
- ti,psil-base = <0x6000>;
-
- ti,sci = <&dmsc>;
- ti,sci-dev-id = <236>;
-
- ti,sci-rm-range-tchan = <0x0d>, /* TX_CHAN */
- <0x0f>; /* TX_HCHAN */
- ti,sci-rm-range-rchan = <0x0a>, /* RX_CHAN */
- <0x0b>; /* RX_HCHAN */
- ti,sci-rm-range-rflow = <0x00>; /* GP RFLOW */
+ dma-controller@285c0000 {
u-boot,dm-spl;
};
};
-
- mcu_cpsw: ethernet@046000000 {
- compatible = "ti,j721e-cpsw-nuss";
- #address-cells = <2>;
- #size-cells = <2>;
- reg = <0x0 0x46000000 0x0 0x200000>;
- reg-names = "cpsw_nuss";
- ranges;
- dma-coherent;
- clocks = <&k3_clks 18 22>;
- clock-names = "fck";
- power-domains = <&k3_pds 18 TI_SCI_PD_EXCLUSIVE>;
- ti,psil-base = <0x7000>;
- cpsw-phy-sel = <&phy_sel>;
-
- dmas = <&mcu_udmap &mcu_cpsw 0 UDMA_DIR_TX>,
- <&mcu_udmap &mcu_cpsw 1 UDMA_DIR_TX>,
- <&mcu_udmap &mcu_cpsw 2 UDMA_DIR_TX>,
- <&mcu_udmap &mcu_cpsw 3 UDMA_DIR_TX>,
- <&mcu_udmap &mcu_cpsw 4 UDMA_DIR_TX>,
- <&mcu_udmap &mcu_cpsw 5 UDMA_DIR_TX>,
- <&mcu_udmap &mcu_cpsw 6 UDMA_DIR_TX>,
- <&mcu_udmap &mcu_cpsw 7 UDMA_DIR_TX>,
- <&mcu_udmap &mcu_cpsw 0 UDMA_DIR_RX>;
- dma-names = "tx0", "tx1", "tx2", "tx3",
- "tx4", "tx5", "tx6", "tx7",
- "rx";
-
- ports {
- #address-cells = <1>;
- #size-cells = <0>;
-
- host: host@0 {
- reg = <0>;
- ti,label = "host";
- };
-
- cpsw_port1: port@1 {
- reg = <1>;
- ti,mac-only;
- ti,label = "port1";
- ti,syscon-efuse = <&mcu_conf 0x200>;
- };
- };
-
- davinci_mdio: mdio {
- #address-cells = <1>;
- #size-cells = <0>;
- bus_freq = <1000000>;
- };
-
- cpts {
- clocks = <&k3_clks 18 2>;
- clock-names = "cpts";
- interrupts-extended = <&gic500 GIC_SPI 858 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "cpts";
- ti,cpts-ext-ts-inputs = <4>;
- ti,cpts-periodic-outputs = <2>;
- };
-
- ti,psil-config0 {
- linux,udma-mode = <UDMA_PKT_MODE>;
- statictr-type = <PSIL_STATIC_TR_NONE>;
- ti,needs-epib;
- ti,psd-size = <16>;
- };
-
- ti,psil-config1 {
- linux,udma-mode = <UDMA_PKT_MODE>;
- statictr-type = <PSIL_STATIC_TR_NONE>;
- ti,needs-epib;
- ti,psd-size = <16>;
- };
-
- ti,psil-config2 {
- linux,udma-mode = <UDMA_PKT_MODE>;
- statictr-type = <PSIL_STATIC_TR_NONE>;
- ti,needs-epib;
- ti,psd-size = <16>;
- };
-
- ti,psil-config3 {
- linux,udma-mode = <UDMA_PKT_MODE>;
- statictr-type = <PSIL_STATIC_TR_NONE>;
- ti,needs-epib;
- ti,psd-size = <16>;
- };
-
- ti,psil-config4 {
- linux,udma-mode = <UDMA_PKT_MODE>;
- statictr-type = <PSIL_STATIC_TR_NONE>;
- ti,needs-epib;
- ti,psd-size = <16>;
- };
-
- ti,psil-config5 {
- linux,udma-mode = <UDMA_PKT_MODE>;
- statictr-type = <PSIL_STATIC_TR_NONE>;
- ti,needs-epib;
- ti,psd-size = <16>;
- };
-
- ti,psil-config6 {
- linux,udma-mode = <UDMA_PKT_MODE>;
- statictr-type = <PSIL_STATIC_TR_NONE>;
- ti,needs-epib;
- ti,psd-size = <16>;
- };
-
- ti,psil-config7 {
- linux,udma-mode = <UDMA_PKT_MODE>;
- statictr-type = <PSIL_STATIC_TR_NONE>;
- ti,needs-epib;
- ti,psd-size = <16>;
- };
- };
};
&secure_proxy_main {
@@ -318,6 +151,7 @@
reg = <0x0 0x46000000 0x0 0x200000>,
<0x0 0x40f00200 0x0 0x2>;
reg-names = "cpsw_nuss", "mac_efuse";
+ /delete-property/ ranges;
cpsw-phy-sel@40f04040 {
compatible = "ti,am654-cpsw-phy-sel";
diff --git a/arch/arm/dts/k3-j721e-mcu-wakeup.dtsi b/arch/arm/dts/k3-j721e-mcu-wakeup.dtsi
index 2eed50aa5a4..e6c99ab6980 100644
--- a/arch/arm/dts/k3-j721e-mcu-wakeup.dtsi
+++ b/arch/arm/dts/k3-j721e-mcu-wakeup.dtsi
@@ -35,6 +35,20 @@
};
};
+ mcu_conf: syscon@40f00000 {
+ compatible = "syscon", "simple-mfd";
+ reg = <0x0 0x40f00000 0x0 0x20000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x0 0x0 0x40f00000 0x20000>;
+
+ phy_gmii_sel: phy@4040 {
+ compatible = "ti,am654-phy-gmii-sel";
+ reg = <0x4040 0x4>;
+ #phy-cells = <1>;
+ };
+ };
+
wkup_pmx0: pinmux@4301c000 {
compatible = "pinctrl-single";
/* Proxy 0 addressing */
@@ -199,4 +213,107 @@
clocks = <&k3_clks 195 0>;
power-domains = <&k3_pds 195 TI_SCI_PD_EXCLUSIVE>;
};
+
+ mcu_navss {
+ compatible = "simple-mfd";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+ dma-coherent;
+ dma-ranges;
+
+ ti,sci-dev-id = <232>;
+
+ mcu_ringacc: ringacc@2b800000 {
+ compatible = "ti,am654-navss-ringacc";
+ reg = <0x0 0x2b800000 0x0 0x400000>,
+ <0x0 0x2b000000 0x0 0x400000>,
+ <0x0 0x28590000 0x0 0x100>,
+ <0x0 0x2a500000 0x0 0x40000>;
+ reg-names = "rt", "fifos", "proxy_gcfg", "proxy_target";
+ ti,num-rings = <286>;
+ ti,sci-rm-range-gp-rings = <0x1>; /* GP ring range */
+ ti,sci = <&dmsc>;
+ ti,sci-dev-id = <235>;
+ };
+
+ mcu_udmap: dma-controller@285c0000 {
+ compatible = "ti,j721e-navss-mcu-udmap";
+ reg = <0x0 0x285c0000 0x0 0x100>,
+ <0x0 0x2a800000 0x0 0x40000>,
+ <0x0 0x2aa00000 0x0 0x40000>;
+ reg-names = "gcfg", "rchanrt", "tchanrt";
+ #dma-cells = <1>;
+
+ ti,sci = <&dmsc>;
+ ti,sci-dev-id = <236>;
+ ti,ringacc = <&mcu_ringacc>;
+
+ ti,sci-rm-range-tchan = <0x0d>, /* TX_CHAN */
+ <0x0f>; /* TX_HCHAN */
+ ti,sci-rm-range-rchan = <0x0a>, /* RX_CHAN */
+ <0x0b>; /* RX_HCHAN */
+ ti,sci-rm-range-rflow = <0x00>; /* GP RFLOW */
+ };
+ };
+
+ mcu_cpsw: ethernet@46000000 {
+ compatible = "ti,j721e-cpsw-nuss";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ reg = <0x0 0x46000000 0x0 0x200000>;
+ reg-names = "cpsw_nuss";
+ ranges = <0x0 0x0 0x0 0x46000000 0x0 0x200000>;
+ dma-coherent;
+ clocks = <&k3_clks 18 22>;
+ clock-names = "fck";
+ power-domains = <&k3_pds 18 TI_SCI_PD_EXCLUSIVE>;
+
+ dmas = <&mcu_udmap 0xf000>,
+ <&mcu_udmap 0xf001>,
+ <&mcu_udmap 0xf002>,
+ <&mcu_udmap 0xf003>,
+ <&mcu_udmap 0xf004>,
+ <&mcu_udmap 0xf005>,
+ <&mcu_udmap 0xf006>,
+ <&mcu_udmap 0xf007>,
+ <&mcu_udmap 0x7000>;
+ dma-names = "tx0", "tx1", "tx2", "tx3",
+ "tx4", "tx5", "tx6", "tx7",
+ "rx";
+
+ ethernet-ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpsw_port1: port@1 {
+ reg = <1>;
+ ti,mac-only;
+ label = "port1";
+ ti,syscon-efuse = <&mcu_conf 0x200>;
+ phys = <&phy_gmii_sel 1>;
+ };
+ };
+
+ davinci_mdio: mdio@f00 {
+ compatible = "ti,cpsw-mdio","ti,davinci_mdio";
+ reg = <0x0 0xf00 0x0 0x100>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clocks = <&k3_clks 18 22>;
+ clock-names = "fck";
+ bus_freq = <1000000>;
+ };
+
+ cpts@3d000 {
+ compatible = "ti,am65-cpts";
+ reg = <0x0 0x3d000 0x0 0x400>;
+ clocks = <&k3_clks 18 2>;
+ clock-names = "cpts";
+ interrupts-extended = <&gic500 GIC_SPI 858 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "cpts";
+ ti,cpts-ext-ts-inputs = <4>;
+ ti,cpts-periodic-outputs = <2>;
+ };
+ };
};
diff --git a/arch/arm/mach-k3/common.c b/arch/arm/mach-k3/common.c
index 9695b2236ec..63bf0606166 100644
--- a/arch/arm/mach-k3/common.c
+++ b/arch/arm/mach-k3/common.c
@@ -440,7 +440,7 @@ void spl_board_prepare_for_boot(void)
dcache_disable();
}
-void spl_board_prepare_for_boot_linux(void)
+void spl_board_prepare_for_linux(void)
{
dcache_disable();
}
diff --git a/arch/arm/mach-k3/config.mk b/arch/arm/mach-k3/config.mk
index f6b63db3497..f7afef610c4 100644
--- a/arch/arm/mach-k3/config.mk
+++ b/arch/arm/mach-k3/config.mk
@@ -48,22 +48,23 @@ ALL-y += tiboot3.bin
endif
ifdef CONFIG_ARM64
+
ifeq ($(CONFIG_TI_SECURE_DEVICE),y)
SPL_ITS := u-boot-spl-k3_HS.its
-$(SPL_ITS): FORCE
- IS_HS=1 \
- $(srctree)/tools/k3_fit_atf.sh \
- $(patsubst %,$(obj)/dts/%.dtb,$(subst ",,$(CONFIG_SPL_OF_LIST))) > $@
-
+$(SPL_ITS): export IS_HS=1
ALL-y += tispl.bin_HS
else
SPL_ITS := u-boot-spl-k3.its
-$(SPL_ITS): FORCE
+ALL-y += tispl.bin
+endif
+
+quiet_cmd_k3_mkits = MKITS $@
+cmd_k3_mkits = \
$(srctree)/tools/k3_fit_atf.sh \
$(patsubst %,$(obj)/dts/%.dtb,$(subst ",,$(CONFIG_SPL_OF_LIST))) > $@
-ALL-y += tispl.bin
-endif
+$(SPL_ITS): FORCE
+ $(call cmd,k3_mkits)
endif
else
diff --git a/board/davinci/da8xxevm/da850evm.c b/board/davinci/da8xxevm/da850evm.c
index a3b0f8bf092..c91aeb8dbf5 100644
--- a/board/davinci/da8xxevm/da850evm.c
+++ b/board/davinci/da8xxevm/da850evm.c
@@ -205,7 +205,7 @@ int misc_init_r(void)
}
static const struct pinmux_config gpio_pins[] = {
-#ifdef CONFIG_USE_NOR
+#ifdef CONFIG_MTD_NOR_FLASH
/* GP0[11] is required for NOR to work on Rev 3 EVMs */
{ pinmux(0), 8, 4 }, /* GP0[11] */
#endif
@@ -235,7 +235,7 @@ const struct pinmux_resource pinmuxes[] = {
PINMUX_ITEM(emifa_pins_cs3),
PINMUX_ITEM(emifa_pins_cs4),
PINMUX_ITEM(emifa_pins_nand),
-#elif defined(CONFIG_USE_NOR)
+#elif defined(CONFIG_MTD_NOR_FLASH)
PINMUX_ITEM(emifa_pins_cs2),
PINMUX_ITEM(emifa_pins_nor),
#endif
@@ -341,7 +341,7 @@ int board_init(void)
DAVINCI_SYSCFG_SUSPSRC_UART2),
&davinci_syscfg_regs->suspsrc);
-#ifdef CONFIG_USE_NOR
+#ifdef CONFIG_MTD_NOR_FLASH
/* Set the GPIO direction as output */
clrbits_le32((u32 *)GPIO_BANK0_REG_DIR_ADDR, (0x01 << 11));
diff --git a/board/ti/beagle/beagle.c b/board/ti/beagle/beagle.c
index 9139ad87d40..9ccd566da37 100644
--- a/board/ti/beagle/beagle.c
+++ b/board/ti/beagle/beagle.c
@@ -40,11 +40,6 @@
#include "beagle.h"
#include <command.h>
-#ifdef CONFIG_USB_EHCI_HCD
-#include <usb.h>
-#include <asm/ehci-omap.h>
-#endif
-
#define TWL4030_I2C_BUS 0
#define EXPANSION_EEPROM_I2C_BUS 1
#define EXPANSION_EEPROM_I2C_ADDRESS 0x50
@@ -297,33 +292,6 @@ static void beagle_dvi_pup(void)
}
#endif
-#ifdef CONFIG_USB_MUSB_OMAP2PLUS
-static struct musb_hdrc_config musb_config = {
- .multipoint = 1,
- .dyn_fifo = 1,
- .num_eps = 16,
- .ram_bits = 12,
-};
-
-static struct omap_musb_board_data musb_board_data = {
- .interface_type = MUSB_INTERFACE_ULPI,
-};
-
-static struct musb_hdrc_platform_data musb_plat = {
-#if defined(CONFIG_USB_MUSB_HOST)
- .mode = MUSB_HOST,
-#elif defined(CONFIG_USB_MUSB_GADGET)
- .mode = MUSB_PERIPHERAL,
-#else
-#error "Please define either CONFIG_USB_MUSB_HOST or CONFIG_USB_MUSB_GADGET"
-#endif
- .config = &musb_config,
- .power = 100,
- .platform_ops = &omap2430_ops,
- .board_data = &musb_board_data,
-};
-#endif
-
/*
* Routine: misc_init_r
* Description: Configure board specific parts
@@ -506,10 +474,6 @@ int misc_init_r(void)
omap3_dss_enable();
#endif
-#ifdef CONFIG_USB_MUSB_OMAP2PLUS
- musb_register(&musb_plat, &musb_board_data, (void *)MUSB_BASE);
-#endif
-
if (generate_fake_mac)
omap_die_id_usbethaddr();
@@ -548,37 +512,3 @@ void board_mmc_power_init(void)
twl4030_power_mmc_init(0);
}
#endif
-
-#if defined(CONFIG_USB_EHCI_HCD) && !defined(CONFIG_SPL_BUILD)
-/* Call usb_stop() before starting the kernel */
-void show_boot_progress(int val)
-{
- if (val == BOOTSTAGE_ID_RUN_OS)
- usb_stop();
-}
-
-static struct omap_usbhs_board_data usbhs_bdata = {
- .port_mode[0] = OMAP_EHCI_PORT_MODE_PHY,
- .port_mode[1] = OMAP_EHCI_PORT_MODE_PHY,
- .port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED
-};
-
-int ehci_hcd_init(int index, enum usb_init_type init,
- struct ehci_hccr **hccr, struct ehci_hcor **hcor)
-{
- return omap_ehci_hcd_init(index, &usbhs_bdata, hccr, hcor);
-}
-
-int ehci_hcd_stop(int index)
-{
- return omap_ehci_hcd_stop();
-}
-
-#endif /* CONFIG_USB_EHCI_HCD */
-
-#if defined(CONFIG_USB_ETHER) && defined(CONFIG_USB_MUSB_GADGET)
-int board_eth_init(bd_t *bis)
-{
- return usb_eth_initialize(bis);
-}
-#endif
diff --git a/cmd/nvedit_efi.c b/cmd/nvedit_efi.c
index 29cad38e19b..3f61d5d6ccb 100644
--- a/cmd/nvedit_efi.c
+++ b/cmd/nvedit_efi.c
@@ -9,11 +9,13 @@
#include <common.h>
#include <command.h>
#include <efi_loader.h>
+#include <efi_variable.h>
#include <env.h>
#include <exports.h>
#include <hexdump.h>
#include <malloc.h>
#include <mapmem.h>
+#include <rtc.h>
#include <uuid.h>
#include <linux/kernel.h>
@@ -34,6 +36,7 @@ static const struct {
{EFI_VARIABLE_RUNTIME_ACCESS, "RT"},
{EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS, "AW"},
{EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS, "AT"},
+ {EFI_VARIABLE_READ_ONLY, "RO"},
};
static const struct {
@@ -87,20 +90,22 @@ static void efi_dump_single_var(u16 *name, const efi_guid_t *guid, bool verbose)
{
u32 attributes;
u8 *data;
+ u64 time;
+ struct rtc_time tm;
efi_uintn_t size;
int count, i;
efi_status_t ret;
data = NULL;
size = 0;
- ret = EFI_CALL(efi_get_variable(name, guid, &attributes, &size, data));
+ ret = efi_get_variable_int(name, guid, &attributes, &size, data, &time);
if (ret == EFI_BUFFER_TOO_SMALL) {
data = malloc(size);
if (!data)
goto out;
- ret = EFI_CALL(efi_get_variable(name, guid, &attributes, &size,
- data));
+ ret = efi_get_variable_int(name, guid, &attributes, &size,
+ data, &time);
}
if (ret == EFI_NOT_FOUND) {
printf("Error: \"%ls\" not defined\n", name);
@@ -109,13 +114,16 @@ static void efi_dump_single_var(u16 *name, const efi_guid_t *guid, bool verbose)
if (ret != EFI_SUCCESS)
goto out;
- printf("%ls:\n %s:", name, efi_guid_to_str(guid));
+ rtc_to_tm(time, &tm);
+ printf("%ls:\n %s:\n", name, efi_guid_to_str(guid));
+ if (attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS)
+ printf(" %04d-%02d-%02d %02d:%02d:%02d\n", tm.tm_year,
+ tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
+ printf(" ");
for (count = 0, i = 0; i < ARRAY_SIZE(efi_var_attrs); i++)
if (attributes & efi_var_attrs[i].mask) {
if (count)
putc('|');
- else
- putc(' ');
count++;
puts(efi_var_attrs[i].text);
}
@@ -592,8 +600,8 @@ int do_env_set_efi(struct cmd_tbl *cmdtp, int flag, int argc,
p = var_name16;
utf8_utf16_strncpy(&p, var_name, len + 1);
- ret = EFI_CALL(efi_set_variable(var_name16, &guid, attributes,
- size, value));
+ ret = efi_set_variable_int(var_name16, &guid, attributes, size, value,
+ true);
unmap_sysmem(value);
if (ret == EFI_SUCCESS) {
ret = CMD_RET_SUCCESS;
diff --git a/configs/da850evm_direct_nor_defconfig b/configs/da850evm_direct_nor_defconfig
index 36ef122ba3a..3924895204b 100644
--- a/configs/da850evm_direct_nor_defconfig
+++ b/configs/da850evm_direct_nor_defconfig
@@ -10,7 +10,6 @@ CONFIG_ENV_SIZE=0x2800
CONFIG_ENV_SECT_SIZE=0x20000
CONFIG_DM_GPIO=y
CONFIG_NR_DRAM_BANKS=1
-CONFIG_SYS_EXTRA_OPTIONS="USE_NOR,DIRECT_NOR_BOOT"
CONFIG_BOOTDELAY=3
CONFIG_USE_BOOTARGS=y
CONFIG_BOOTARGS="mem=32M console=ttyS2,115200n8 root=/dev/mtdblock2 rw noinitrd ip=dhcp"
diff --git a/configs/omap3_beagle_defconfig b/configs/omap3_beagle_defconfig
index af5b8ea872a..b08ffc062d2 100644
--- a/configs/omap3_beagle_defconfig
+++ b/configs/omap3_beagle_defconfig
@@ -73,10 +73,13 @@ CONFIG_SYS_NAND_BUSWIDTH_16BIT=y
CONFIG_SYS_NAND_U_BOOT_LOCATIONS=y
CONFIG_SYS_NAND_U_BOOT_OFFS=0x80000
CONFIG_SPL_NAND_SIMPLE=y
+CONFIG_DM_ETH=y
CONFIG_SPI=y
CONFIG_DM_SPI=y
CONFIG_OMAP3_SPI=y
CONFIG_USB=y
+CONFIG_DM_USB=y
+# CONFIG_SPL_DM_USB is not set
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_OMAP3=y
CONFIG_USB_MUSB_GADGET=y
diff --git a/doc/README.davinci b/doc/README.davinci
index 6522c24eea1..607531af2a8 100644
--- a/doc/README.davinci
+++ b/doc/README.davinci
@@ -37,11 +37,15 @@ Bootloaders
===============
For DA850 an SPL (secondary program loader, see doc/README.SPL) is provided
-to load U-Boot directly from SPI flash. The SPL takes care of the low level
+to load U-Boot from SPI flash, MMC or NAND. The SPL takes care of the low level
initialization.
-The SPL is built as u-boot.ais for all DA850 defconfigs. The resulting
-image file can be programmed to the SPI flash of the DA850 EVM/LCDK.
+The SPL is built as u-boot.ais for all DA850 defconfigs except those booting
+from NOR flash. The resulting image file can be programmed to the SPI flash
+of the DA850 EVM/LCDK.
+
+Devices that support booting from NOR utilize execute in place (XIP) and do
+not require SPL to perform low level initialization.
Environment Variables
=====================
diff --git a/doc/api/efi.rst b/doc/api/efi.rst
index d5114f05b3b..cb2a1c897e6 100644
--- a/doc/api/efi.rst
+++ b/doc/api/efi.rst
@@ -93,6 +93,8 @@ Runtime services
Variable services
~~~~~~~~~~~~~~~~~
+.. kernel-doc:: include/efi_variable.h
+ :internal:
.. kernel-doc:: lib/efi_loader/efi_variable.c
:internal:
diff --git a/drivers/dma/ti/Kconfig b/drivers/dma/ti/Kconfig
index 3d5498326c4..9cbd5f334dc 100644
--- a/drivers/dma/ti/Kconfig
+++ b/drivers/dma/ti/Kconfig
@@ -8,7 +8,11 @@ config TI_K3_NAVSS_UDMA
select DMA
select TI_K3_NAVSS_RINGACC
select TI_K3_NAVSS_PSILCFG
+ select TI_K3_PSIL
default n
help
Support for UDMA used in K3 devices.
endif
+
+config TI_K3_PSIL
+ bool
diff --git a/drivers/dma/ti/Makefile b/drivers/dma/ti/Makefile
index de2f9ac91a4..4ea9c626ccd 100644
--- a/drivers/dma/ti/Makefile
+++ b/drivers/dma/ti/Makefile
@@ -1,3 +1,7 @@
# SPDX-License-Identifier: GPL-2.0+
obj-$(CONFIG_TI_K3_NAVSS_UDMA) += k3-udma.o
+obj-$(CONFIG_TI_K3_PSIL) += k3-psil-data.o
+k3-psil-data-y += k3-psil.o
+k3-psil-data-$(CONFIG_SOC_K3_AM6) += k3-psil-am654.o
+k3-psil-data-$(CONFIG_SOC_K3_J721E) += k3-psil-j721e.o
diff --git a/drivers/dma/ti/k3-psil-am654.c b/drivers/dma/ti/k3-psil-am654.c
new file mode 100644
index 00000000000..f95d99cfd39
--- /dev/null
+++ b/drivers/dma/ti/k3-psil-am654.c
@@ -0,0 +1,89 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com
+ * Author: Peter Ujfalusi <peter.ujfalusi@ti.com>
+ */
+
+#include <linux/kernel.h>
+
+#include "k3-psil-priv.h"
+
+#define PSIL_ETHERNET(x) \
+ { \
+ .thread_id = x, \
+ .ep_config = { \
+ .ep_type = PSIL_EP_NATIVE, \
+ .pkt_mode = 1, \
+ .needs_epib = 1, \
+ .psd_size = 16, \
+ }, \
+ }
+
+/* PSI-L source thread IDs, used for RX (DMA_DEV_TO_MEM) */
+static struct psil_ep am654_src_ep_map[] = {
+ /* PRU_ICSSG0 */
+ PSIL_ETHERNET(0x4100),
+ PSIL_ETHERNET(0x4101),
+ PSIL_ETHERNET(0x4102),
+ PSIL_ETHERNET(0x4103),
+ /* PRU_ICSSG1 */
+ PSIL_ETHERNET(0x4200),
+ PSIL_ETHERNET(0x4201),
+ PSIL_ETHERNET(0x4202),
+ PSIL_ETHERNET(0x4203),
+ /* PRU_ICSSG2 */
+ PSIL_ETHERNET(0x4300),
+ PSIL_ETHERNET(0x4301),
+ PSIL_ETHERNET(0x4302),
+ PSIL_ETHERNET(0x4303),
+ /* CPSW0 */
+ PSIL_ETHERNET(0x7000),
+};
+
+/* PSI-L destination thread IDs, used for TX (DMA_MEM_TO_DEV) */
+static struct psil_ep am654_dst_ep_map[] = {
+ /* PRU_ICSSG0 */
+ PSIL_ETHERNET(0xc100),
+ PSIL_ETHERNET(0xc101),
+ PSIL_ETHERNET(0xc102),
+ PSIL_ETHERNET(0xc103),
+ PSIL_ETHERNET(0xc104),
+ PSIL_ETHERNET(0xc105),
+ PSIL_ETHERNET(0xc106),
+ PSIL_ETHERNET(0xc107),
+ /* PRU_ICSSG1 */
+ PSIL_ETHERNET(0xc200),
+ PSIL_ETHERNET(0xc201),
+ PSIL_ETHERNET(0xc202),
+ PSIL_ETHERNET(0xc203),
+ PSIL_ETHERNET(0xc204),
+ PSIL_ETHERNET(0xc205),
+ PSIL_ETHERNET(0xc206),
+ PSIL_ETHERNET(0xc207),
+ /* PRU_ICSSG2 */
+ PSIL_ETHERNET(0xc300),
+ PSIL_ETHERNET(0xc301),
+ PSIL_ETHERNET(0xc302),
+ PSIL_ETHERNET(0xc303),
+ PSIL_ETHERNET(0xc304),
+ PSIL_ETHERNET(0xc305),
+ PSIL_ETHERNET(0xc306),
+ PSIL_ETHERNET(0xc307),
+ /* CPSW0 */
+ PSIL_ETHERNET(0xf000),
+ PSIL_ETHERNET(0xf001),
+ PSIL_ETHERNET(0xf002),
+ PSIL_ETHERNET(0xf003),
+ PSIL_ETHERNET(0xf004),
+ PSIL_ETHERNET(0xf005),
+ PSIL_ETHERNET(0xf006),
+ PSIL_ETHERNET(0xf007),
+};
+
+struct psil_ep_map am654_ep_map = {
+ .name = "am654",
+ .src = am654_src_ep_map,
+ .src_count = ARRAY_SIZE(am654_src_ep_map),
+ .dst = am654_dst_ep_map,
+ .dst_count = ARRAY_SIZE(am654_dst_ep_map),
+};
diff --git a/drivers/dma/ti/k3-psil-j721e.c b/drivers/dma/ti/k3-psil-j721e.c
new file mode 100644
index 00000000000..105ffd946f4
--- /dev/null
+++ b/drivers/dma/ti/k3-psil-j721e.c
@@ -0,0 +1,47 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com
+ * Author: Peter Ujfalusi <peter.ujfalusi@ti.com>
+ */
+
+#include <linux/kernel.h>
+
+#include "k3-psil-priv.h"
+
+#define PSIL_ETHERNET(x) \
+ { \
+ .thread_id = x, \
+ .ep_config = { \
+ .ep_type = PSIL_EP_NATIVE, \
+ .pkt_mode = 1, \
+ .needs_epib = 1, \
+ .psd_size = 16, \
+ }, \
+ }
+
+/* PSI-L source thread IDs, used for RX (DMA_DEV_TO_MEM) */
+static struct psil_ep j721e_src_ep_map[] = {
+ /* CPSW0 */
+ PSIL_ETHERNET(0x7000),
+};
+
+/* PSI-L destination thread IDs, used for TX (DMA_MEM_TO_DEV) */
+static struct psil_ep j721e_dst_ep_map[] = {
+ /* CPSW0 */
+ PSIL_ETHERNET(0xf000),
+ PSIL_ETHERNET(0xf001),
+ PSIL_ETHERNET(0xf002),
+ PSIL_ETHERNET(0xf003),
+ PSIL_ETHERNET(0xf004),
+ PSIL_ETHERNET(0xf005),
+ PSIL_ETHERNET(0xf006),
+ PSIL_ETHERNET(0xf007),
+};
+
+struct psil_ep_map j721e_ep_map = {
+ .name = "j721e",
+ .src = j721e_src_ep_map,
+ .src_count = ARRAY_SIZE(j721e_src_ep_map),
+ .dst = j721e_dst_ep_map,
+ .dst_count = ARRAY_SIZE(j721e_dst_ep_map),
+};
diff --git a/drivers/dma/ti/k3-psil-priv.h b/drivers/dma/ti/k3-psil-priv.h
new file mode 100644
index 00000000000..d3a38322b1d
--- /dev/null
+++ b/drivers/dma/ti/k3-psil-priv.h
@@ -0,0 +1,43 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com
+ */
+
+#ifndef K3_PSIL_PRIV_H_
+#define K3_PSIL_PRIV_H_
+
+#include "k3-psil.h"
+
+struct psil_ep {
+ u32 thread_id;
+ struct psil_endpoint_config ep_config;
+};
+
+/**
+ * struct psil_ep_map - PSI-L thread ID configuration maps
+ * @name: Name of the map, set it to the name of the SoC
+ * @src: Array of source PSI-L thread configurations
+ * @src_count: Number of entries in the src array
+ * @dst: Array of destination PSI-L thread configurations
+ * @dst_count: Number of entries in the dst array
+ *
+ * In case of symmetric configuration for a matching src/dst thread (for example
+ * 0x4400 and 0xc400) only the src configuration can be present. If no dst
+ * configuration found the code will look for (dst_thread_id & ~0x8000) to find
+ * the symmetric match.
+ */
+struct psil_ep_map {
+ char *name;
+ struct psil_ep *src;
+ int src_count;
+ struct psil_ep *dst;
+ int dst_count;
+};
+
+struct psil_endpoint_config *psil_get_ep_config(u32 thread_id);
+
+/* SoC PSI-L endpoint maps */
+extern struct psil_ep_map am654_ep_map;
+extern struct psil_ep_map j721e_ep_map;
+
+#endif /* K3_PSIL_PRIV_H_ */
diff --git a/drivers/dma/ti/k3-psil.c b/drivers/dma/ti/k3-psil.c
new file mode 100644
index 00000000000..b5c92b28293
--- /dev/null
+++ b/drivers/dma/ti/k3-psil.c
@@ -0,0 +1,42 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com
+ * Author: Peter Ujfalusi <peter.ujfalusi@ti.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/err.h>
+
+#include "k3-psil-priv.h"
+
+static const struct psil_ep_map *soc_ep_map;
+
+struct psil_endpoint_config *psil_get_ep_config(u32 thread_id)
+{
+ int i;
+
+ if (!soc_ep_map) {
+ if (IS_ENABLED(CONFIG_SOC_K3_AM6))
+ soc_ep_map = &am654_ep_map;
+ else if (IS_ENABLED(CONFIG_SOC_K3_J721E))
+ soc_ep_map = &j721e_ep_map;
+ }
+
+ if (thread_id & K3_PSIL_DST_THREAD_ID_OFFSET && soc_ep_map->dst) {
+ /* check in destination thread map */
+ for (i = 0; i < soc_ep_map->dst_count; i++) {
+ if (soc_ep_map->dst[i].thread_id == thread_id)
+ return &soc_ep_map->dst[i].ep_config;
+ }
+ }
+
+ thread_id &= ~K3_PSIL_DST_THREAD_ID_OFFSET;
+ if (soc_ep_map->src) {
+ for (i = 0; i < soc_ep_map->src_count; i++) {
+ if (soc_ep_map->src[i].thread_id == thread_id)
+ return &soc_ep_map->src[i].ep_config;
+ }
+ }
+
+ return ERR_PTR(-ENOENT);
+}
diff --git a/drivers/dma/ti/k3-psil.h b/drivers/dma/ti/k3-psil.h
new file mode 100644
index 00000000000..53c61b45958
--- /dev/null
+++ b/drivers/dma/ti/k3-psil.h
@@ -0,0 +1,67 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com
+ */
+
+#ifndef K3_PSIL_H_
+#define K3_PSIL_H_
+
+#include <linux/types.h>
+
+#define K3_PSIL_DST_THREAD_ID_OFFSET 0x8000
+
+struct device;
+
+/**
+ * enum udma_tp_level - Channel Throughput Levels
+ * @UDMA_TP_NORMAL: Normal channel
+ * @UDMA_TP_HIGH: High Throughput channel
+ * @UDMA_TP_ULTRAHIGH: Ultra High Throughput channel
+ */
+enum udma_tp_level {
+ UDMA_TP_NORMAL = 0,
+ UDMA_TP_HIGH,
+ UDMA_TP_ULTRAHIGH,
+ UDMA_TP_LAST,
+};
+
+/**
+ * enum psil_endpoint_type - PSI-L Endpoint type
+ * @PSIL_EP_NATIVE: Normal channel
+ * @PSIL_EP_PDMA_XY: XY mode PDMA
+ * @PSIL_EP_PDMA_MCAN: MCAN mode PDMA
+ * @PSIL_EP_PDMA_AASRC: AASRC mode PDMA
+ */
+enum psil_endpoint_type {
+ PSIL_EP_NATIVE = 0,
+ PSIL_EP_PDMA_XY,
+ PSIL_EP_PDMA_MCAN,
+ PSIL_EP_PDMA_AASRC,
+};
+
+/**
+ * struct psil_endpoint_config - PSI-L Endpoint configuration
+ * @ep_type: PSI-L endpoint type
+ * @pkt_mode: If set, the channel must be in Packet mode, otherwise in
+ * TR mode
+ * @notdpkt: TDCM must be suppressed on the TX channel
+ * @needs_epib: Endpoint needs EPIB
+ * @psd_size: If set, PSdata is used by the endpoint
+ * @channel_tpl: Desired throughput level for the channel
+ * @pdma_acc32: ACC32 must be enabled on the PDMA side
+ * @pdma_burst: BURST must be enabled on the PDMA side
+ */
+struct psil_endpoint_config {
+ enum psil_endpoint_type ep_type;
+
+ unsigned pkt_mode:1;
+ unsigned notdpkt:1;
+ unsigned needs_epib:1;
+ u32 psd_size;
+ enum udma_tp_level channel_tpl;
+
+ /* PDMA properties, valid for PSIL_EP_PDMA_* */
+ unsigned pdma_acc32:1;
+ unsigned pdma_burst:1;
+};
+#endif /* K3_PSIL_H_ */
diff --git a/drivers/dma/ti/k3-udma.c b/drivers/dma/ti/k3-udma.c
index 2ce16c8e27f..57d9fbfabbf 100644
--- a/drivers/dma/ti/k3-udma.c
+++ b/drivers/dma/ti/k3-udma.c
@@ -22,7 +22,6 @@
#include <dma.h>
#include <dma-uclass.h>
#include <linux/delay.h>
-#include <dt-bindings/dma/k3-udma.h>
#include <linux/bitmap.h>
#include <linux/err.h>
#include <linux/soc/ti/k3-navss-ringacc.h>
@@ -31,12 +30,7 @@
#include <linux/soc/ti/ti_sci_protocol.h>
#include "k3-udma-hwdef.h"
-
-#if BITS_PER_LONG == 64
-#define RINGACC_RING_USE_PROXY (0)
-#else
-#define RINGACC_RING_USE_PROXY (1)
-#endif
+#include "k3-psil-priv.h"
#define K3_UDMA_MAX_RFLOWS 1024
@@ -65,12 +59,28 @@ struct udma_rchan {
void __iomem *reg_rt;
int id;
- struct k3_nav_ring *fd_ring; /* Free Descriptor ring */
- struct k3_nav_ring *r_ring; /* Receive ring*/
+};
+
+#define UDMA_FLAG_PDMA_ACC32 BIT(0)
+#define UDMA_FLAG_PDMA_BURST BIT(1)
+#define UDMA_FLAG_TDTYPE BIT(2)
+
+struct udma_match_data {
+ u32 psil_base;
+ bool enable_memcpy_support;
+ u32 flags;
+ u32 statictr_z_mask;
+ u32 rchan_oes_offset;
+
+ u8 tpl_levels;
+ u32 level_start_idx[];
};
struct udma_rflow {
int id;
+
+ struct k3_nav_ring *fd_ring; /* Free Descriptor ring */
+ struct k3_nav_ring *r_ring; /* Receive ring*/
};
enum udma_rm_range {
@@ -114,12 +124,34 @@ struct udma_dev {
struct udma_rchan *rchans;
struct udma_rflow *rflows;
+ struct udma_match_data *match_data;
+
struct udma_chan *channels;
u32 psil_base;
u32 ch_count;
};
+struct udma_chan_config {
+ u32 psd_size; /* size of Protocol Specific Data */
+ u32 metadata_size; /* (needs_epib ? 16:0) + psd_size */
+ u32 hdesc_size; /* Size of a packet descriptor in packet mode */
+ int remote_thread_id;
+ u32 atype;
+ u32 src_thread;
+ u32 dst_thread;
+ enum psil_endpoint_type ep_type;
+ enum udma_tp_level channel_tpl; /* Channel Throughput Level */
+
+ enum dma_direction dir;
+
+ unsigned int pkt_mode:1; /* TR or packet */
+ unsigned int needs_epib:1; /* EPIB is needed for the communication or not */
+ unsigned int enable_acc32:1;
+ unsigned int enable_burst:1;
+ unsigned int notdpkt:1; /* Suppress sending TDC packet */
+};
+
struct udma_chan {
struct udma_dev *ud;
char name[20];
@@ -132,20 +164,11 @@ struct udma_chan {
u32 bcnt; /* number of bytes completed since the start of the channel */
- bool pkt_mode; /* TR or packet */
- bool needs_epib; /* EPIB is needed for the communication or not */
- u32 psd_size; /* size of Protocol Specific Data */
- u32 metadata_size; /* (needs_epib ? 16:0) + psd_size */
- int slave_thread_id;
- u32 src_thread;
- u32 dst_thread;
- u32 static_tr_type;
+ struct udma_chan_config config;
u32 id;
- enum dma_direction dir;
struct cppi5_host_desc_t *desc_tx;
- u32 hdesc_size;
bool in_use;
void *desc_rx;
u32 num_rx_bufs;
@@ -271,7 +294,7 @@ static inline bool udma_is_chan_running(struct udma_chan *uc)
u32 trt_ctl = 0;
u32 rrt_ctl = 0;
- switch (uc->dir) {
+ switch (uc->config.dir) {
case DMA_DEV_TO_MEM:
rrt_ctl = udma_rchanrt_read(uc->rchan, UDMA_RCHAN_RT_CTL_REG);
pr_debug("%s: rrt_ctl: 0x%08x (peer: 0x%08x)\n",
@@ -305,9 +328,9 @@ static int udma_pop_from_ring(struct udma_chan *uc, dma_addr_t *addr)
struct k3_nav_ring *ring = NULL;
int ret = -ENOENT;
- switch (uc->dir) {
+ switch (uc->config.dir) {
case DMA_DEV_TO_MEM:
- ring = uc->rchan->r_ring;
+ ring = uc->rflow->r_ring;
break;
case DMA_MEM_TO_DEV:
ring = uc->tchan->tc_ring;
@@ -330,10 +353,10 @@ static void udma_reset_rings(struct udma_chan *uc)
struct k3_nav_ring *ring1 = NULL;
struct k3_nav_ring *ring2 = NULL;
- switch (uc->dir) {
+ switch (uc->config.dir) {
case DMA_DEV_TO_MEM:
- ring1 = uc->rchan->fd_ring;
- ring2 = uc->rchan->r_ring;
+ ring1 = uc->rflow->fd_ring;
+ ring2 = uc->rflow->r_ring;
break;
case DMA_MEM_TO_DEV:
ring1 = uc->tchan->t_ring;
@@ -392,7 +415,7 @@ static inline int udma_stop_hard(struct udma_chan *uc)
{
pr_debug("%s: ENTER (chan%d)\n", __func__, uc->id);
- switch (uc->dir) {
+ switch (uc->config.dir) {
case DMA_DEV_TO_MEM:
udma_rchanrt_write(uc->rchan, UDMA_RCHAN_RT_PEER_RT_EN_REG, 0);
udma_rchanrt_write(uc->rchan, UDMA_RCHAN_RT_CTL_REG, 0);
@@ -418,9 +441,8 @@ static int udma_start(struct udma_chan *uc)
if (udma_is_chan_running(uc))
goto out;
- pr_debug("%s: chan:%d dir:%s (static_tr_type: %d)\n",
- __func__, uc->id, udma_get_dir_text(uc->dir),
- uc->static_tr_type);
+ pr_debug("%s: chan:%d dir:%s\n",
+ __func__, uc->id, udma_get_dir_text(uc->config.dir));
/* Make sure that we clear the teardown bit, if it is set */
udma_stop_hard(uc);
@@ -428,7 +450,7 @@ static int udma_start(struct udma_chan *uc)
/* Reset all counters */
udma_reset_counters(uc);
- switch (uc->dir) {
+ switch (uc->config.dir) {
case DMA_DEV_TO_MEM:
udma_rchanrt_write(uc->rchan, UDMA_RCHAN_RT_CTL_REG,
UDMA_CHAN_RT_CTL_EN);
@@ -530,10 +552,10 @@ static inline void udma_stop_dev2mem(struct udma_chan *uc, bool sync)
static inline int udma_stop(struct udma_chan *uc)
{
pr_debug("%s: chan:%d dir:%s\n",
- __func__, uc->id, udma_get_dir_text(uc->dir));
+ __func__, uc->id, udma_get_dir_text(uc->config.dir));
udma_reset_counters(uc);
- switch (uc->dir) {
+ switch (uc->config.dir) {
case DMA_DEV_TO_MEM:
udma_stop_dev2mem(uc, true);
break;
@@ -768,21 +790,14 @@ static int udma_alloc_tx_resources(struct udma_chan *uc)
if (ret)
return ret;
- uc->tchan->t_ring = k3_nav_ringacc_request_ring(
- ud->ringacc, uc->tchan->id,
- RINGACC_RING_USE_PROXY);
- if (!uc->tchan->t_ring) {
+ ret = k3_nav_ringacc_request_rings_pair(ud->ringacc, uc->tchan->id, -1,
+ &uc->tchan->t_ring,
+ &uc->tchan->tc_ring);
+ if (ret) {
ret = -EBUSY;
goto err_tx_ring;
}
- uc->tchan->tc_ring = k3_nav_ringacc_request_ring(
- ud->ringacc, -1, RINGACC_RING_USE_PROXY);
- if (!uc->tchan->tc_ring) {
- ret = -EBUSY;
- goto err_txc_ring;
- }
-
memset(&ring_cfg, 0, sizeof(ring_cfg));
ring_cfg.size = 16;
ring_cfg.elm_size = K3_NAV_RINGACC_RING_ELSIZE_8;
@@ -799,7 +814,6 @@ static int udma_alloc_tx_resources(struct udma_chan *uc)
err_ringcfg:
k3_nav_ringacc_ring_free(uc->tchan->tc_ring);
uc->tchan->tc_ring = NULL;
-err_txc_ring:
k3_nav_ringacc_ring_free(uc->tchan->t_ring);
uc->tchan->t_ring = NULL;
err_tx_ring:
@@ -813,12 +827,15 @@ static void udma_free_rx_resources(struct udma_chan *uc)
if (!uc->rchan)
return;
- k3_nav_ringacc_ring_free(uc->rchan->fd_ring);
- k3_nav_ringacc_ring_free(uc->rchan->r_ring);
- uc->rchan->fd_ring = NULL;
- uc->rchan->r_ring = NULL;
+ if (uc->rflow) {
+ k3_nav_ringacc_ring_free(uc->rflow->fd_ring);
+ k3_nav_ringacc_ring_free(uc->rflow->r_ring);
+ uc->rflow->fd_ring = NULL;
+ uc->rflow->r_ring = NULL;
+
+ udma_put_rflow(uc);
+ }
- udma_put_rflow(uc);
udma_put_rchan(uc);
}
@@ -826,6 +843,7 @@ static int udma_alloc_rx_resources(struct udma_chan *uc)
{
struct k3_nav_ring_cfg ring_cfg;
struct udma_dev *ud = uc->ud;
+ struct udma_rflow *rflow;
int fd_ring_id;
int ret;
@@ -834,7 +852,7 @@ static int udma_alloc_rx_resources(struct udma_chan *uc)
return ret;
/* For MEM_TO_MEM we don't need rflow or rings */
- if (uc->dir == DMA_MEM_TO_MEM)
+ if (uc->config.dir == DMA_MEM_TO_MEM)
return 0;
ret = udma_get_rflow(uc, uc->rchan->id);
@@ -845,40 +863,31 @@ static int udma_alloc_rx_resources(struct udma_chan *uc)
fd_ring_id = ud->tchan_cnt + ud->echan_cnt + uc->rchan->id;
- uc->rchan->fd_ring = k3_nav_ringacc_request_ring(
- ud->ringacc, fd_ring_id,
- RINGACC_RING_USE_PROXY);
- if (!uc->rchan->fd_ring) {
+ rflow = uc->rflow;
+ ret = k3_nav_ringacc_request_rings_pair(ud->ringacc, fd_ring_id, -1,
+ &rflow->fd_ring, &rflow->r_ring);
+ if (ret) {
ret = -EBUSY;
goto err_rx_ring;
}
- uc->rchan->r_ring = k3_nav_ringacc_request_ring(
- ud->ringacc, -1, RINGACC_RING_USE_PROXY);
- if (!uc->rchan->r_ring) {
- ret = -EBUSY;
- goto err_rxc_ring;
- }
-
memset(&ring_cfg, 0, sizeof(ring_cfg));
ring_cfg.size = 16;
ring_cfg.elm_size = K3_NAV_RINGACC_RING_ELSIZE_8;
ring_cfg.mode = K3_NAV_RINGACC_RING_MODE_RING;
- ret = k3_nav_ringacc_ring_cfg(uc->rchan->fd_ring, &ring_cfg);
- ret |= k3_nav_ringacc_ring_cfg(uc->rchan->r_ring, &ring_cfg);
-
+ ret = k3_nav_ringacc_ring_cfg(rflow->fd_ring, &ring_cfg);
+ ret |= k3_nav_ringacc_ring_cfg(rflow->r_ring, &ring_cfg);
if (ret)
goto err_ringcfg;
return 0;
err_ringcfg:
- k3_nav_ringacc_ring_free(uc->rchan->r_ring);
- uc->rchan->r_ring = NULL;
-err_rxc_ring:
- k3_nav_ringacc_ring_free(uc->rchan->fd_ring);
- uc->rchan->fd_ring = NULL;
+ k3_nav_ringacc_ring_free(rflow->r_ring);
+ rflow->r_ring = NULL;
+ k3_nav_ringacc_ring_free(rflow->fd_ring);
+ rflow->fd_ring = NULL;
err_rx_ring:
udma_put_rflow(uc);
err_rflow:
@@ -896,7 +905,7 @@ static int udma_alloc_tchan_sci_req(struct udma_chan *uc)
u32 mode;
int ret;
- if (uc->pkt_mode)
+ if (uc->config.pkt_mode)
mode = TI_SCI_RM_UDMAP_CHAN_TYPE_PKT_PBRR;
else
mode = TI_SCI_RM_UDMAP_CHAN_TYPE_3RDP_BCOPY_PBRR;
@@ -907,11 +916,11 @@ static int udma_alloc_tchan_sci_req(struct udma_chan *uc)
req.nav_id = tisci_rm->tisci_dev_id;
req.index = uc->tchan->id;
req.tx_chan_type = mode;
- if (uc->dir == DMA_MEM_TO_MEM)
+ if (uc->config.dir == DMA_MEM_TO_MEM)
req.tx_fetch_size = sizeof(struct cppi5_desc_hdr_t) >> 2;
else
- req.tx_fetch_size = cppi5_hdesc_calc_size(uc->needs_epib,
- uc->psd_size,
+ req.tx_fetch_size = cppi5_hdesc_calc_size(uc->config.needs_epib,
+ uc->config.psd_size,
0) >> 2;
req.txcq_qnum = tc_ring;
@@ -925,8 +934,8 @@ static int udma_alloc_tchan_sci_req(struct udma_chan *uc)
static int udma_alloc_rchan_sci_req(struct udma_chan *uc)
{
struct udma_dev *ud = uc->ud;
- int fd_ring = k3_nav_ringacc_get_ring_id(uc->rchan->fd_ring);
- int rx_ring = k3_nav_ringacc_get_ring_id(uc->rchan->r_ring);
+ int fd_ring = k3_nav_ringacc_get_ring_id(uc->rflow->fd_ring);
+ int rx_ring = k3_nav_ringacc_get_ring_id(uc->rflow->r_ring);
int tc_ring = k3_nav_ringacc_get_ring_id(uc->tchan->tc_ring);
struct ti_sci_msg_rm_udmap_rx_ch_cfg req = { 0 };
struct ti_sci_msg_rm_udmap_flow_cfg flow_req = { 0 };
@@ -934,7 +943,7 @@ static int udma_alloc_rchan_sci_req(struct udma_chan *uc)
u32 mode;
int ret;
- if (uc->pkt_mode)
+ if (uc->config.pkt_mode)
mode = TI_SCI_RM_UDMAP_CHAN_TYPE_PKT_PBRR;
else
mode = TI_SCI_RM_UDMAP_CHAN_TYPE_3RDP_BCOPY_PBRR;
@@ -947,16 +956,16 @@ static int udma_alloc_rchan_sci_req(struct udma_chan *uc)
req.nav_id = tisci_rm->tisci_dev_id;
req.index = uc->rchan->id;
req.rx_chan_type = mode;
- if (uc->dir == DMA_MEM_TO_MEM) {
+ if (uc->config.dir == DMA_MEM_TO_MEM) {
req.rx_fetch_size = sizeof(struct cppi5_desc_hdr_t) >> 2;
req.rxcq_qnum = tc_ring;
} else {
- req.rx_fetch_size = cppi5_hdesc_calc_size(uc->needs_epib,
- uc->psd_size,
+ req.rx_fetch_size = cppi5_hdesc_calc_size(uc->config.needs_epib,
+ uc->config.psd_size,
0) >> 2;
req.rxcq_qnum = rx_ring;
}
- if (uc->rflow->id != uc->rchan->id && uc->dir != DMA_MEM_TO_MEM) {
+ if (uc->rflow->id != uc->rchan->id && uc->config.dir != DMA_MEM_TO_MEM) {
req.flowid_start = uc->rflow->id;
req.flowid_cnt = 1;
}
@@ -967,7 +976,7 @@ static int udma_alloc_rchan_sci_req(struct udma_chan *uc)
uc->rchan->id, ret);
return ret;
}
- if (uc->dir == DMA_MEM_TO_MEM)
+ if (uc->config.dir == DMA_MEM_TO_MEM)
return ret;
flow_req.valid_params =
@@ -989,12 +998,12 @@ static int udma_alloc_rchan_sci_req(struct udma_chan *uc)
flow_req.nav_id = tisci_rm->tisci_dev_id;
flow_req.flow_index = uc->rflow->id;
- if (uc->needs_epib)
+ if (uc->config.needs_epib)
flow_req.rx_einfo_present = 1;
else
flow_req.rx_einfo_present = 0;
- if (uc->psd_size)
+ if (uc->config.psd_size)
flow_req.rx_psinfo_present = 1;
else
flow_req.rx_psinfo_present = 0;
@@ -1027,11 +1036,12 @@ static int udma_alloc_chan_resources(struct udma_chan *uc)
int ret;
pr_debug("%s: chan:%d as %s\n",
- __func__, uc->id, udma_get_dir_text(uc->dir));
+ __func__, uc->id, udma_get_dir_text(uc->config.dir));
- switch (uc->dir) {
+ switch (uc->config.dir) {
case DMA_MEM_TO_MEM:
/* Non synchronized - mem to mem type of transfer */
+ uc->config.pkt_mode = false;
ret = udma_get_chan_pair(uc);
if (ret)
return ret;
@@ -1044,8 +1054,8 @@ static int udma_alloc_chan_resources(struct udma_chan *uc)
if (ret)
goto err_free_res;
- uc->src_thread = ud->psil_base + uc->tchan->id;
- uc->dst_thread = (ud->psil_base + uc->rchan->id) | 0x8000;
+ uc->config.src_thread = ud->psil_base + uc->tchan->id;
+ uc->config.dst_thread = (ud->psil_base + uc->rchan->id) | 0x8000;
break;
case DMA_MEM_TO_DEV:
/* Slave transfer synchronized - mem to dev (TX) trasnfer */
@@ -1053,10 +1063,9 @@ static int udma_alloc_chan_resources(struct udma_chan *uc)
if (ret)
goto err_free_res;
- uc->src_thread = ud->psil_base + uc->tchan->id;
- uc->dst_thread = uc->slave_thread_id;
- if (!(uc->dst_thread & 0x8000))
- uc->dst_thread |= 0x8000;
+ uc->config.src_thread = ud->psil_base + uc->tchan->id;
+ uc->config.dst_thread = uc->config.remote_thread_id;
+ uc->config.dst_thread |= 0x8000;
break;
case DMA_DEV_TO_MEM:
@@ -1065,19 +1074,19 @@ static int udma_alloc_chan_resources(struct udma_chan *uc)
if (ret)
goto err_free_res;
- uc->src_thread = uc->slave_thread_id;
- uc->dst_thread = (ud->psil_base + uc->rchan->id) | 0x8000;
+ uc->config.src_thread = uc->config.remote_thread_id;
+ uc->config.dst_thread = (ud->psil_base + uc->rchan->id) | 0x8000;
break;
default:
/* Can not happen */
pr_debug("%s: chan:%d invalid direction (%u)\n",
- __func__, uc->id, uc->dir);
+ __func__, uc->id, uc->config.dir);
return -EINVAL;
}
/* We have channel indexes and rings */
- if (uc->dir == DMA_MEM_TO_MEM) {
+ if (uc->config.dir == DMA_MEM_TO_MEM) {
ret = udma_alloc_tchan_sci_req(uc);
if (ret)
goto err_free_res;
@@ -1087,7 +1096,7 @@ static int udma_alloc_chan_resources(struct udma_chan *uc)
goto err_free_res;
} else {
/* Slave transfer */
- if (uc->dir == DMA_MEM_TO_DEV) {
+ if (uc->config.dir == DMA_MEM_TO_DEV) {
ret = udma_alloc_tchan_sci_req(uc);
if (ret)
goto err_free_res;
@@ -1108,7 +1117,7 @@ static int udma_alloc_chan_resources(struct udma_chan *uc)
}
/* PSI-L pairing */
- ret = udma_navss_psil_pair(ud, uc->src_thread, uc->dst_thread);
+ ret = udma_navss_psil_pair(ud, uc->config.src_thread, uc->config.dst_thread);
if (ret) {
dev_err(ud->dev, "k3_nav_psil_request_link fail\n");
goto err_free_res;
@@ -1119,7 +1128,7 @@ static int udma_alloc_chan_resources(struct udma_chan *uc)
err_free_res:
udma_free_tx_resources(uc);
udma_free_rx_resources(uc);
- uc->slave_thread_id = -1;
+ uc->config.remote_thread_id = -1;
return ret;
}
@@ -1128,15 +1137,15 @@ static void udma_free_chan_resources(struct udma_chan *uc)
/* Some configuration to UDMA-P channel: disable, reset, whatever */
/* Release PSI-L pairing */
- udma_navss_psil_unpair(uc->ud, uc->src_thread, uc->dst_thread);
+ udma_navss_psil_unpair(uc->ud, uc->config.src_thread, uc->config.dst_thread);
/* Reset the rings for a new start */
udma_reset_rings(uc);
udma_free_tx_resources(uc);
udma_free_rx_resources(uc);
- uc->slave_thread_id = -1;
- uc->dir = DMA_MEM_TO_MEM;
+ uc->config.remote_thread_id = -1;
+ uc->config.dir = DMA_MEM_TO_MEM;
}
static int udma_get_mmrs(struct udevice *dev)
@@ -1293,12 +1302,8 @@ static int udma_probe(struct udevice *dev)
if (IS_ERR(ud->ringacc))
return PTR_ERR(ud->ringacc);
- ud->psil_base = dev_read_u32_default(dev, "ti,psil-base", 0);
- if (!ud->psil_base) {
- dev_info(dev,
- "Missing ti,psil-base property, using %d.\n", ret);
- return -EINVAL;
- }
+ ud->match_data = (void *)dev_get_driver_data(dev);
+ ud->psil_base = ud->match_data->psil_base;
ret = uclass_get_device_by_phandle(UCLASS_FIRMWARE, dev,
"ti,sci", &tisci_dev);
@@ -1364,10 +1369,10 @@ static int udma_probe(struct udevice *dev)
uc->ud = ud;
uc->id = i;
- uc->slave_thread_id = -1;
+ uc->config.remote_thread_id = -1;
uc->tchan = NULL;
uc->rchan = NULL;
- uc->dir = DMA_MEM_TO_MEM;
+ uc->config.dir = DMA_MEM_TO_MEM;
sprintf(uc->name, "UDMA chan%d\n", i);
if (!i)
uc->in_use = true;
@@ -1514,6 +1519,7 @@ static int udma_transfer(struct udevice *dev, int direction,
static int udma_request(struct dma *dma)
{
struct udma_dev *ud = dev_get_priv(dma->dev);
+ struct udma_chan_config *ucc;
struct udma_chan *uc;
unsigned long dummy;
int ret;
@@ -1524,30 +1530,27 @@ static int udma_request(struct dma *dma)
}
uc = &ud->channels[dma->id];
+ ucc = &uc->config;
ret = udma_alloc_chan_resources(uc);
if (ret) {
dev_err(dma->dev, "alloc dma res failed %d\n", ret);
return -EINVAL;
}
- uc->hdesc_size = cppi5_hdesc_calc_size(uc->needs_epib,
- uc->psd_size, 0);
- uc->hdesc_size = ALIGN(uc->hdesc_size, ARCH_DMA_MINALIGN);
-
- if (uc->dir == DMA_MEM_TO_DEV) {
- uc->desc_tx = dma_alloc_coherent(uc->hdesc_size, &dummy);
- memset(uc->desc_tx, 0, uc->hdesc_size);
+ if (uc->config.dir == DMA_MEM_TO_DEV) {
+ uc->desc_tx = dma_alloc_coherent(ucc->hdesc_size, &dummy);
+ memset(uc->desc_tx, 0, ucc->hdesc_size);
} else {
uc->desc_rx = dma_alloc_coherent(
- uc->hdesc_size * UDMA_RX_DESC_NUM, &dummy);
- memset(uc->desc_rx, 0, uc->hdesc_size * UDMA_RX_DESC_NUM);
+ ucc->hdesc_size * UDMA_RX_DESC_NUM, &dummy);
+ memset(uc->desc_rx, 0, ucc->hdesc_size * UDMA_RX_DESC_NUM);
}
uc->in_use = true;
uc->desc_rx_cur = 0;
uc->num_rx_bufs = 0;
- if (uc->dir == DMA_DEV_TO_MEM) {
+ if (uc->config.dir == DMA_DEV_TO_MEM) {
uc->cfg_data.flow_id_base = uc->rflow->id;
uc->cfg_data.flow_id_cnt = 1;
}
@@ -1632,7 +1635,7 @@ static int udma_send(struct dma *dma, void *src, size_t len, void *metadata)
}
uc = &ud->channels[dma->id];
- if (uc->dir != DMA_MEM_TO_DEV)
+ if (uc->config.dir != DMA_MEM_TO_DEV)
return -EINVAL;
tc_ring_id = k3_nav_ringacc_get_ring_id(uc->tchan->tc_ring);
@@ -1642,8 +1645,8 @@ static int udma_send(struct dma *dma, void *src, size_t len, void *metadata)
cppi5_hdesc_reset_hbdesc(desc_tx);
cppi5_hdesc_init(desc_tx,
- uc->needs_epib ? CPPI5_INFO0_HDESC_EPIB_PRESENT : 0,
- uc->psd_size);
+ uc->config.needs_epib ? CPPI5_INFO0_HDESC_EPIB_PRESENT : 0,
+ uc->config.psd_size);
cppi5_hdesc_set_pktlen(desc_tx, len);
cppi5_hdesc_attach_buf(desc_tx, dma_src, len, dma_src, len);
cppi5_desc_set_pktids(&desc_tx->hdr, uc->id, 0x3fff);
@@ -1656,7 +1659,7 @@ static int udma_send(struct dma *dma, void *src, size_t len, void *metadata)
ALIGN((unsigned long)dma_src + len,
ARCH_DMA_MINALIGN));
flush_dcache_range((unsigned long)desc_tx,
- ALIGN((unsigned long)desc_tx + uc->hdesc_size,
+ ALIGN((unsigned long)desc_tx + uc->config.hdesc_size,
ARCH_DMA_MINALIGN));
ret = udma_push_to_ring(uc->tchan->t_ring, uc->desc_tx);
@@ -1674,6 +1677,7 @@ static int udma_send(struct dma *dma, void *src, size_t len, void *metadata)
static int udma_receive(struct dma *dma, void **dst, void *metadata)
{
struct udma_dev *ud = dev_get_priv(dma->dev);
+ struct udma_chan_config *ucc;
struct cppi5_host_desc_t *desc_rx;
dma_addr_t buf_dma;
struct udma_chan *uc;
@@ -1686,13 +1690,14 @@ static int udma_receive(struct dma *dma, void **dst, void *metadata)
return -EINVAL;
}
uc = &ud->channels[dma->id];
+ ucc = &uc->config;
- if (uc->dir != DMA_DEV_TO_MEM)
+ if (uc->config.dir != DMA_DEV_TO_MEM)
return -EINVAL;
if (!uc->num_rx_bufs)
return -EINVAL;
- ret = k3_nav_ringacc_ring_pop(uc->rchan->r_ring, &desc_rx);
+ ret = k3_nav_ringacc_ring_pop(uc->rflow->r_ring, &desc_rx);
if (ret && ret != -ENODATA) {
dev_err(dma->dev, "rx dma fail ch_id:%lu %d\n", dma->id, ret);
return ret;
@@ -1702,7 +1707,7 @@ static int udma_receive(struct dma *dma, void **dst, void *metadata)
/* invalidate cache data */
invalidate_dcache_range((ulong)desc_rx,
- (ulong)(desc_rx + uc->hdesc_size));
+ (ulong)(desc_rx + ucc->hdesc_size));
cppi5_hdesc_get_obuf(desc_rx, &buf_dma, &buf_dma_len);
pkt_len = cppi5_hdesc_get_pktlen(desc_rx);
@@ -1721,10 +1726,10 @@ static int udma_receive(struct dma *dma, void **dst, void *metadata)
static int udma_of_xlate(struct dma *dma, struct ofnode_phandle_args *args)
{
+ struct udma_chan_config *ucc;
struct udma_dev *ud = dev_get_priv(dma->dev);
struct udma_chan *uc = &ud->channels[0];
- ofnode chconf_node, slave_node;
- char prop[50];
+ struct psil_endpoint_config *ep_config;
u32 val;
for (val = 0; val < ud->ch_count; val++) {
@@ -1736,48 +1741,40 @@ static int udma_of_xlate(struct dma *dma, struct ofnode_phandle_args *args)
if (val == ud->ch_count)
return -EBUSY;
- uc->dir = DMA_DEV_TO_MEM;
- if (args->args[2] == UDMA_DIR_TX)
- uc->dir = DMA_MEM_TO_DEV;
-
- slave_node = ofnode_get_by_phandle(args->args[0]);
- if (!ofnode_valid(slave_node)) {
- dev_err(ud->dev, "slave node is missing\n");
- return -EINVAL;
- }
-
- snprintf(prop, sizeof(prop), "ti,psil-config%u", args->args[1]);
- chconf_node = ofnode_find_subnode(slave_node, prop);
- if (!ofnode_valid(chconf_node)) {
- dev_err(ud->dev, "Channel configuration node is missing\n");
- return -EINVAL;
- }
+ ucc = &uc->config;
+ ucc->remote_thread_id = args->args[0];
+ if (ucc->remote_thread_id & K3_PSIL_DST_THREAD_ID_OFFSET)
+ ucc->dir = DMA_MEM_TO_DEV;
+ else
+ ucc->dir = DMA_DEV_TO_MEM;
- if (!ofnode_read_u32(chconf_node, "linux,udma-mode", &val)) {
- if (val == UDMA_PKT_MODE)
- uc->pkt_mode = true;
+ ep_config = psil_get_ep_config(ucc->remote_thread_id);
+ if (IS_ERR(ep_config)) {
+ dev_err(ud->dev, "No configuration for psi-l thread 0x%04x\n",
+ uc->config.remote_thread_id);
+ ucc->dir = DMA_MEM_TO_MEM;
+ ucc->remote_thread_id = -1;
+ return false;
}
- if (!ofnode_read_u32(chconf_node, "statictr-type", &val))
- uc->static_tr_type = val;
+ ucc->pkt_mode = ep_config->pkt_mode;
+ ucc->channel_tpl = ep_config->channel_tpl;
+ ucc->notdpkt = ep_config->notdpkt;
+ ucc->ep_type = ep_config->ep_type;
- uc->needs_epib = ofnode_read_bool(chconf_node, "ti,needs-epib");
- if (!ofnode_read_u32(chconf_node, "ti,psd-size", &val))
- uc->psd_size = val;
- uc->metadata_size = (uc->needs_epib ? 16 : 0) + uc->psd_size;
+ ucc->needs_epib = ep_config->needs_epib;
+ ucc->psd_size = ep_config->psd_size;
+ ucc->metadata_size = (ucc->needs_epib ? CPPI5_INFO0_HDESC_EPIB_SIZE : 0) + ucc->psd_size;
- if (ofnode_read_u32(slave_node, "ti,psil-base", &val)) {
- dev_err(ud->dev, "ti,psil-base is missing\n");
- return -EINVAL;
- }
-
- uc->slave_thread_id = val + args->args[1];
+ ucc->hdesc_size = cppi5_hdesc_calc_size(ucc->needs_epib,
+ ucc->psd_size, 0);
+ ucc->hdesc_size = ALIGN(ucc->hdesc_size, ARCH_DMA_MINALIGN);
dma->id = uc->id;
pr_debug("Allocated dma chn:%lu epib:%d psdata:%u meta:%u thread_id:%x\n",
- dma->id, uc->needs_epib,
- uc->psd_size, uc->metadata_size,
- uc->slave_thread_id);
+ dma->id, ucc->needs_epib,
+ ucc->psd_size, ucc->metadata_size,
+ ucc->remote_thread_id);
return 0;
}
@@ -1796,29 +1793,29 @@ int udma_prepare_rcv_buf(struct dma *dma, void *dst, size_t size)
}
uc = &ud->channels[dma->id];
- if (uc->dir != DMA_DEV_TO_MEM)
+ if (uc->config.dir != DMA_DEV_TO_MEM)
return -EINVAL;
if (uc->num_rx_bufs >= UDMA_RX_DESC_NUM)
return -EINVAL;
desc_num = uc->desc_rx_cur % UDMA_RX_DESC_NUM;
- desc_rx = uc->desc_rx + (desc_num * uc->hdesc_size);
+ desc_rx = uc->desc_rx + (desc_num * uc->config.hdesc_size);
dma_dst = (dma_addr_t)dst;
cppi5_hdesc_reset_hbdesc(desc_rx);
cppi5_hdesc_init(desc_rx,
- uc->needs_epib ? CPPI5_INFO0_HDESC_EPIB_PRESENT : 0,
- uc->psd_size);
+ uc->config.needs_epib ? CPPI5_INFO0_HDESC_EPIB_PRESENT : 0,
+ uc->config.psd_size);
cppi5_hdesc_set_pktlen(desc_rx, size);
cppi5_hdesc_attach_buf(desc_rx, dma_dst, size, dma_dst, size);
flush_dcache_range((unsigned long)desc_rx,
- ALIGN((unsigned long)desc_rx + uc->hdesc_size,
+ ALIGN((unsigned long)desc_rx + uc->config.hdesc_size,
ARCH_DMA_MINALIGN));
- udma_push_to_ring(uc->rchan->fd_ring, desc_rx);
+ udma_push_to_ring(uc->rflow->fd_ring, desc_rx);
uc->num_rx_bufs++;
uc->desc_rx_cur++;
@@ -1859,10 +1856,73 @@ static const struct dma_ops udma_ops = {
.get_cfg = udma_get_cfg,
};
+static struct udma_match_data am654_main_data = {
+ .psil_base = 0x1000,
+ .enable_memcpy_support = true,
+ .statictr_z_mask = GENMASK(11, 0),
+ .rchan_oes_offset = 0x200,
+ .tpl_levels = 2,
+ .level_start_idx = {
+ [0] = 8, /* Normal channels */
+ [1] = 0, /* High Throughput channels */
+ },
+};
+
+static struct udma_match_data am654_mcu_data = {
+ .psil_base = 0x6000,
+ .enable_memcpy_support = true,
+ .statictr_z_mask = GENMASK(11, 0),
+ .rchan_oes_offset = 0x200,
+ .tpl_levels = 2,
+ .level_start_idx = {
+ [0] = 2, /* Normal channels */
+ [1] = 0, /* High Throughput channels */
+ },
+};
+
+static struct udma_match_data j721e_main_data = {
+ .psil_base = 0x1000,
+ .enable_memcpy_support = true,
+ .flags = UDMA_FLAG_PDMA_ACC32 | UDMA_FLAG_PDMA_BURST | UDMA_FLAG_TDTYPE,
+ .statictr_z_mask = GENMASK(23, 0),
+ .rchan_oes_offset = 0x400,
+ .tpl_levels = 3,
+ .level_start_idx = {
+ [0] = 16, /* Normal channels */
+ [1] = 4, /* High Throughput channels */
+ [2] = 0, /* Ultra High Throughput channels */
+ },
+};
+
+static struct udma_match_data j721e_mcu_data = {
+ .psil_base = 0x6000,
+ .enable_memcpy_support = true,
+ .flags = UDMA_FLAG_PDMA_ACC32 | UDMA_FLAG_PDMA_BURST | UDMA_FLAG_TDTYPE,
+ .statictr_z_mask = GENMASK(23, 0),
+ .rchan_oes_offset = 0x400,
+ .tpl_levels = 2,
+ .level_start_idx = {
+ [0] = 2, /* Normal channels */
+ [1] = 0, /* High Throughput channels */
+ },
+};
+
static const struct udevice_id udma_ids[] = {
- { .compatible = "ti,k3-navss-udmap" },
- { .compatible = "ti,j721e-navss-mcu-udmap" },
- { }
+ {
+ .compatible = "ti,am654-navss-main-udmap",
+ .data = (ulong)&am654_main_data,
+ },
+ {
+ .compatible = "ti,am654-navss-mcu-udmap",
+ .data = (ulong)&am654_mcu_data,
+ }, {
+ .compatible = "ti,j721e-navss-main-udmap",
+ .data = (ulong)&j721e_main_data,
+ }, {
+ .compatible = "ti,j721e-navss-mcu-udmap",
+ .data = (ulong)&j721e_mcu_data,
+ },
+ { /* Sentinel */ },
};
U_BOOT_DRIVER(ti_edma3) = {
diff --git a/drivers/mmc/omap_hsmmc.c b/drivers/mmc/omap_hsmmc.c
index 0e05fe4cfcb..db1f85125f9 100644
--- a/drivers/mmc/omap_hsmmc.c
+++ b/drivers/mmc/omap_hsmmc.c
@@ -843,7 +843,7 @@ static int omap_hsmmc_init_setup(struct mmc *mmc)
omap_hsmmc_conf_bus_power(mmc, (reg_val & VS33_3V3SUP) ?
MMC_SIGNAL_VOLTAGE_330 : MMC_SIGNAL_VOLTAGE_180);
#else
- writel(DTW_1_BITMODE | SDBP_PWROFF | SDVS_3V0, &mmc_base->hctl);
+ writel(DTW_1_BITMODE | SDBP_PWROFF | SDVS_3V3, &mmc_base->hctl);
writel(readl(&mmc_base->capa) | VS33_3V3SUP | VS18_1V8SUP,
&mmc_base->capa);
#endif
diff --git a/drivers/net/ti/am65-cpsw-nuss.c b/drivers/net/ti/am65-cpsw-nuss.c
index 85f3e49c055..971bdcdfda9 100644
--- a/drivers/net/ti/am65-cpsw-nuss.c
+++ b/drivers/net/ti/am65-cpsw-nuss.c
@@ -61,6 +61,9 @@
#define AM65_CPSW_ALE_PN_CTL_REG_MODE_FORWARD 0x3
#define AM65_CPSW_ALE_PN_CTL_REG_MAC_ONLY BIT(11)
+#define AM65_CPSW_ALE_THREADMAPDEF_REG 0x134
+#define AM65_CPSW_ALE_DEFTHREAD_EN BIT(15)
+
#define AM65_CPSW_MACSL_CTL_REG 0x0
#define AM65_CPSW_MACSL_CTL_REG_IFCTL_A BIT(15)
#define AM65_CPSW_MACSL_CTL_EXT_EN BIT(18)
@@ -364,6 +367,9 @@ static int am65_cpsw_start(struct udevice *dev)
writel(AM65_CPSW_ALE_PN_CTL_REG_MODE_FORWARD,
common->ale_base + AM65_CPSW_ALE_PN_CTL_REG(0));
+ writel(AM65_CPSW_ALE_DEFTHREAD_EN,
+ common->ale_base + AM65_CPSW_ALE_THREADMAPDEF_REG);
+
/* PORT x configuration */
/* Port x Max length register */
@@ -680,7 +686,7 @@ static int am65_cpsw_probe_cpsw(struct udevice *dev)
AM65_CPSW_CPSW_NU_ALE_BASE;
cpsw_common->mdio_base = cpsw_common->ss_base + AM65_CPSW_MDIO_BASE;
- ports_np = dev_read_subnode(dev, "ports");
+ ports_np = dev_read_subnode(dev, "ethernet-ports");
if (!ofnode_valid(ports_np)) {
ret = -ENOENT;
goto out;
@@ -746,13 +752,6 @@ static int am65_cpsw_probe_cpsw(struct udevice *dev)
goto out;
}
- node = dev_read_subnode(dev, "mdio");
- if (!ofnode_valid(node)) {
- dev_err(dev, "can't find mdio\n");
- ret = -ENOENT;
- goto out;
- }
-
cpsw_common->bus_freq =
dev_read_u32_default(dev, "bus_freq",
AM65_CPSW_MDIO_BUS_FREQ_DEF);
diff --git a/drivers/soc/ti/k3-navss-ringacc.c b/drivers/soc/ti/k3-navss-ringacc.c
index ecc4b8b5a06..c48e9befe4b 100644
--- a/drivers/soc/ti/k3-navss-ringacc.c
+++ b/drivers/soc/ti/k3-navss-ringacc.c
@@ -127,6 +127,22 @@ struct k3_nav_ring_ops {
};
/**
+ * struct k3_nav_ring_state - Internal state tracking structure
+ *
+ * @free: Number of free entries
+ * @occ: Occupancy
+ * @windex: Write index
+ * @rindex: Read index
+ */
+struct k3_nav_ring_state {
+ u32 free;
+ u32 occ;
+ u32 windex;
+ u32 rindex;
+ u32 tdown_complete:1;
+};
+
+/**
* struct k3_nav_ring - RA Ring descriptor
*
* @rt - Ring control/status registers
@@ -139,10 +155,6 @@ struct k3_nav_ring_ops {
* @elm_size - Size of the ring element
* @mode - Ring mode
* @flags - flags
- * @free - Number of free elements
- * @occ - Ring occupancy
- * @windex - Write index (only for @K3_NAV_RINGACC_RING_MODE_RING)
- * @rindex - Read index (only for @K3_NAV_RINGACC_RING_MODE_RING)
* @ring_id - Ring Id
* @parent - Pointer on struct @k3_nav_ringacc
* @use_count - Use count for shared rings
@@ -161,16 +173,17 @@ struct k3_nav_ring {
u32 flags;
#define KNAV_RING_FLAG_BUSY BIT(1)
#define K3_NAV_RING_FLAG_SHARED BIT(2)
- u32 free;
- u32 occ;
- u32 windex;
- u32 rindex;
+ struct k3_nav_ring_state state;
u32 ring_id;
struct k3_nav_ringacc *parent;
u32 use_count;
int proxy_id;
};
+struct k3_nav_ringacc_ops {
+ int (*init)(struct udevice *dev, struct k3_nav_ringacc *ringacc);
+};
+
/**
* struct k3_nav_ringacc - Rings accelerator descriptor
*
@@ -186,6 +199,7 @@ struct k3_nav_ring {
* @tisci - pointer ti-sci handle
* @tisci_ring_ops - ti-sci rings ops
* @tisci_dev_id - ti-sci device id
+ * @ops: SoC specific ringacc operation
*/
struct k3_nav_ringacc {
struct udevice *dev;
@@ -204,6 +218,8 @@ struct k3_nav_ringacc {
const struct ti_sci_handle *tisci;
const struct ti_sci_rm_ringacc_ops *tisci_ring_ops;
u32 tisci_dev_id;
+
+ const struct k3_nav_ringacc_ops *ops;
};
static long k3_nav_ringacc_ring_get_fifo_pos(struct k3_nav_ring *ring)
@@ -312,6 +328,29 @@ error:
return NULL;
}
+int k3_nav_ringacc_request_rings_pair(struct k3_nav_ringacc *ringacc,
+ int fwd_id, int compl_id,
+ struct k3_nav_ring **fwd_ring,
+ struct k3_nav_ring **compl_ring)
+{
+ int ret = 0;
+
+ if (!fwd_ring || !compl_ring)
+ return -EINVAL;
+
+ *fwd_ring = k3_nav_ringacc_request_ring(ringacc, fwd_id, 0);
+ if (!(*fwd_ring))
+ return -ENODEV;
+
+ *compl_ring = k3_nav_ringacc_request_ring(ringacc, compl_id, 0);
+ if (!(*compl_ring)) {
+ k3_nav_ringacc_ring_free(*fwd_ring);
+ ret = -ENODEV;
+ }
+
+ return ret;
+}
+
static void k3_ringacc_ring_reset_sci(struct k3_nav_ring *ring)
{
struct k3_nav_ringacc *ringacc = ring->parent;
@@ -338,10 +377,7 @@ void k3_nav_ringacc_ring_reset(struct k3_nav_ring *ring)
if (!ring || !(ring->flags & KNAV_RING_FLAG_BUSY))
return;
- ring->occ = 0;
- ring->free = 0;
- ring->rindex = 0;
- ring->windex = 0;
+ memset(&ring->state, 0, sizeof(ring->state));
k3_ringacc_ring_reset_sci(ring);
}
@@ -546,10 +582,7 @@ int k3_nav_ringacc_ring_cfg(struct k3_nav_ring *ring,
ring->size = cfg->size;
ring->elm_size = cfg->elm_size;
ring->mode = cfg->mode;
- ring->occ = 0;
- ring->free = 0;
- ring->rindex = 0;
- ring->windex = 0;
+ memset(&ring->state, 0, sizeof(ring->state));
if (ring->proxy_id != K3_RINGACC_PROXY_NOT_USED)
ring->proxy = ringacc->proxy_target_base +
@@ -625,10 +658,10 @@ u32 k3_nav_ringacc_ring_get_free(struct k3_nav_ring *ring)
if (!ring || !(ring->flags & KNAV_RING_FLAG_BUSY))
return -EINVAL;
- if (!ring->free)
- ring->free = ring->size - ringacc_readl(&ring->rt->occ);
+ if (!ring->state.free)
+ ring->state.free = ring->size - ringacc_readl(&ring->rt->occ);
- return ring->free;
+ return ring->state.free;
}
u32 k3_nav_ringacc_ring_get_occ(struct k3_nav_ring *ring)
@@ -694,21 +727,21 @@ static int k3_nav_ringacc_ring_access_proxy(
pr_debug("proxy:memcpy_fromio(x): --> ptr(%p), mode:%d\n",
ptr, access_mode);
memcpy_fromio(elem, ptr, (4 << ring->elm_size));
- ring->occ--;
+ ring->state.occ--;
break;
case K3_RINGACC_ACCESS_MODE_PUSH_TAIL:
case K3_RINGACC_ACCESS_MODE_PUSH_HEAD:
pr_debug("proxy:memcpy_toio(x): --> ptr(%p), mode:%d\n",
ptr, access_mode);
memcpy_toio(ptr, elem, (4 << ring->elm_size));
- ring->free--;
+ ring->state.free--;
break;
default:
return -EINVAL;
}
pr_debug("proxy: free%d occ%d\n",
- ring->free, ring->occ);
+ ring->state.free, ring->state.occ);
return 0;
}
@@ -763,21 +796,21 @@ static int k3_nav_ringacc_ring_access_io(
pr_debug("memcpy_fromio(x): --> ptr(%p), mode:%d\n",
ptr, access_mode);
memcpy_fromio(elem, ptr, (4 << ring->elm_size));
- ring->occ--;
+ ring->state.occ--;
break;
case K3_RINGACC_ACCESS_MODE_PUSH_TAIL:
case K3_RINGACC_ACCESS_MODE_PUSH_HEAD:
pr_debug("memcpy_toio(x): --> ptr(%p), mode:%d\n",
ptr, access_mode);
memcpy_toio(ptr, elem, (4 << ring->elm_size));
- ring->free--;
+ ring->state.free--;
break;
default:
return -EINVAL;
}
pr_debug("free%d index%d occ%d index%d\n",
- ring->free, ring->windex, ring->occ, ring->rindex);
+ ring->state.free, ring->state.windex, ring->state.occ, ring->state.rindex);
return 0;
}
@@ -810,7 +843,7 @@ static int k3_nav_ringacc_ring_push_mem(struct k3_nav_ring *ring, void *elem)
{
void *elem_ptr;
- elem_ptr = k3_nav_ringacc_get_elm_addr(ring, ring->windex);
+ elem_ptr = k3_nav_ringacc_get_elm_addr(ring, ring->state.windex);
memcpy(elem_ptr, elem, (4 << ring->elm_size));
@@ -819,12 +852,12 @@ static int k3_nav_ringacc_ring_push_mem(struct k3_nav_ring *ring, void *elem)
ring->size * (4 << ring->elm_size),
ARCH_DMA_MINALIGN));
- ring->windex = (ring->windex + 1) % ring->size;
- ring->free--;
+ ring->state.windex = (ring->state.windex + 1) % ring->size;
+ ring->state.free--;
ringacc_writel(1, &ring->rt->db);
pr_debug("ring_push_mem: free%d index%d\n",
- ring->free, ring->windex);
+ ring->state.free, ring->state.windex);
return 0;
}
@@ -833,7 +866,7 @@ static int k3_nav_ringacc_ring_pop_mem(struct k3_nav_ring *ring, void *elem)
{
void *elem_ptr;
- elem_ptr = k3_nav_ringacc_get_elm_addr(ring, ring->rindex);
+ elem_ptr = k3_nav_ringacc_get_elm_addr(ring, ring->state.rindex);
invalidate_dcache_range((unsigned long)ring->ring_mem_virt,
ALIGN((unsigned long)ring->ring_mem_virt +
@@ -842,12 +875,12 @@ static int k3_nav_ringacc_ring_pop_mem(struct k3_nav_ring *ring, void *elem)
memcpy(elem, elem_ptr, (4 << ring->elm_size));
- ring->rindex = (ring->rindex + 1) % ring->size;
- ring->occ--;
+ ring->state.rindex = (ring->state.rindex + 1) % ring->size;
+ ring->state.occ--;
ringacc_writel(-1, &ring->rt->db);
pr_debug("ring_pop_mem: occ%d index%d pos_ptr%p\n",
- ring->occ, ring->rindex, elem_ptr);
+ ring->state.occ, ring->state.rindex, elem_ptr);
return 0;
}
@@ -859,7 +892,7 @@ int k3_nav_ringacc_ring_push(struct k3_nav_ring *ring, void *elem)
return -EINVAL;
pr_debug("ring_push%d: free%d index%d\n",
- ring->ring_id, ring->free, ring->windex);
+ ring->ring_id, ring->state.free, ring->state.windex);
if (k3_nav_ringacc_ring_is_full(ring))
return -ENOMEM;
@@ -878,7 +911,7 @@ int k3_nav_ringacc_ring_push_head(struct k3_nav_ring *ring, void *elem)
return -EINVAL;
pr_debug("ring_push_head: free%d index%d\n",
- ring->free, ring->windex);
+ ring->state.free, ring->state.windex);
if (k3_nav_ringacc_ring_is_full(ring))
return -ENOMEM;
@@ -896,13 +929,13 @@ int k3_nav_ringacc_ring_pop(struct k3_nav_ring *ring, void *elem)
if (!ring || !(ring->flags & KNAV_RING_FLAG_BUSY))
return -EINVAL;
- if (!ring->occ)
- ring->occ = k3_nav_ringacc_ring_get_occ(ring);
+ if (!ring->state.occ)
+ ring->state.occ = k3_nav_ringacc_ring_get_occ(ring);
pr_debug("ring_pop%d: occ%d index%d\n",
- ring->ring_id, ring->occ, ring->rindex);
+ ring->ring_id, ring->state.occ, ring->state.rindex);
- if (!ring->occ)
+ if (!ring->state.occ && !ring->state.tdown_complete)
return -ENODATA;
if (ring->ops && ring->ops->pop_head)
@@ -918,13 +951,13 @@ int k3_nav_ringacc_ring_pop_tail(struct k3_nav_ring *ring, void *elem)
if (!ring || !(ring->flags & KNAV_RING_FLAG_BUSY))
return -EINVAL;
- if (!ring->occ)
- ring->occ = k3_nav_ringacc_ring_get_occ(ring);
+ if (!ring->state.occ)
+ ring->state.occ = k3_nav_ringacc_ring_get_occ(ring);
pr_debug("ring_pop_tail: occ%d index%d\n",
- ring->occ, ring->rindex);
+ ring->state.occ, ring->state.rindex);
- if (!ring->occ)
+ if (!ring->state.occ)
return -ENODATA;
if (ring->ops && ring->ops->pop_tail)
@@ -982,18 +1015,11 @@ static int k3_nav_ringacc_probe_dt(struct k3_nav_ringacc *ringacc)
return 0;
}
-static int k3_nav_ringacc_probe(struct udevice *dev)
+static int k3_nav_ringacc_init(struct udevice *dev, struct k3_nav_ringacc *ringacc)
{
- struct k3_nav_ringacc *ringacc;
void __iomem *base_fifo, *base_rt;
int ret, i;
- ringacc = dev_get_priv(dev);
- if (!ringacc)
- return -ENOMEM;
-
- ringacc->dev = dev;
-
ret = k3_nav_ringacc_probe_dt(ringacc);
if (ret)
return ret;
@@ -1063,11 +1089,42 @@ static int k3_nav_ringacc_probe(struct udevice *dev)
return 0;
}
+struct ringacc_match_data {
+ struct k3_nav_ringacc_ops ops;
+};
+
+static struct ringacc_match_data k3_nav_ringacc_data = {
+ .ops = {
+ .init = k3_nav_ringacc_init,
+ },
+};
+
static const struct udevice_id knav_ringacc_ids[] = {
- { .compatible = "ti,am654-navss-ringacc" },
+ { .compatible = "ti,am654-navss-ringacc", .data = (ulong)&k3_nav_ringacc_data, },
{},
};
+static int k3_nav_ringacc_probe(struct udevice *dev)
+{
+ struct k3_nav_ringacc *ringacc;
+ int ret;
+ const struct ringacc_match_data *match_data;
+
+ match_data = (struct ringacc_match_data *)dev_get_driver_data(dev);
+
+ ringacc = dev_get_priv(dev);
+ if (!ringacc)
+ return -ENOMEM;
+
+ ringacc->dev = dev;
+ ringacc->ops = &match_data->ops;
+ ret = ringacc->ops->init(dev, ringacc);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
U_BOOT_DRIVER(k3_navss_ringacc) = {
.name = "k3-navss-ringacc",
.id = UCLASS_MISC,
diff --git a/fs/fat/fat_write.c b/fs/fat/fat_write.c
index b16a39d3ffb..a2682b5f465 100644
--- a/fs/fat/fat_write.c
+++ b/fs/fat/fat_write.c
@@ -500,8 +500,6 @@ flush_dir(fat_itr *itr)
nsects * mydata->sect_size);
}
-static __u8 tmpbuf_cluster[MAX_CLUSTSIZE] __aligned(ARCH_DMA_MINALIGN);
-
/*
* Read and modify data on existing and consecutive cluster blocks
*/
@@ -509,6 +507,7 @@ static int
get_set_cluster(fsdata *mydata, __u32 clustnum, loff_t pos, __u8 *buffer,
loff_t size, loff_t *gotsize)
{
+ static u8 *tmpbuf_cluster;
unsigned int bytesperclust = mydata->clust_size * mydata->sect_size;
__u32 startsect;
loff_t wsize;
@@ -518,6 +517,12 @@ get_set_cluster(fsdata *mydata, __u32 clustnum, loff_t pos, __u8 *buffer,
if (!size)
return 0;
+ if (!tmpbuf_cluster) {
+ tmpbuf_cluster = memalign(ARCH_DMA_MINALIGN, MAX_CLUSTSIZE);
+ if (!tmpbuf_cluster)
+ return -1;
+ }
+
assert(pos < bytesperclust);
startsect = clust_to_sect(mydata, clustnum);
diff --git a/include/configs/da850evm.h b/include/configs/da850evm.h
index 2bb4e47496b..11aca4afe11 100644
--- a/include/configs/da850evm.h
+++ b/include/configs/da850evm.h
@@ -13,10 +13,6 @@
/*
* Board
*/
-/* check if direct NOR boot config is used */
-#ifndef CONFIG_DIRECT_NOR_BOOT
-#define CONFIG_USE_SPIFLASH
-#endif
/*
* SoC Configuration
@@ -28,7 +24,7 @@
#define CONFIG_SYS_HZ_CLOCK clk_get(DAVINCI_AUXCLK_CLKID)
#define CONFIG_SKIP_LOWLEVEL_INIT_ONLY
-#ifdef CONFIG_DIRECT_NOR_BOOT
+#ifdef CONFIG_MTD_NOR_FLASH
#define CONFIG_SYS_DV_NOR_BOOT_CFG (0x11)
#endif
@@ -107,10 +103,6 @@
#define CONFIG_SYS_SPI_CLK clk_get(DAVINCI_SPI1_CLKID)
-#ifdef CONFIG_USE_SPIFLASH
-#define CONFIG_SYS_SPI_U_BOOT_SIZE 0x40000
-#endif
-
/*
* I2C Configuration
*/
@@ -170,7 +162,7 @@
#define CONFIG_NET_RETRY_COUNT 10
#endif
-#ifdef CONFIG_USE_NOR
+#ifdef CONFIG_MTD_NOR_FLASH
#define CONFIG_SYS_MAX_FLASH_BANKS 1 /* max number of flash banks */
#define CONFIG_SYS_FLASH_SECT_SZ (128 << 10) /* 128KB */
#define CONFIG_SYS_FLASH_BASE DAVINCI_ASYNC_EMIF_DATA_CE2_BASE
@@ -223,16 +215,11 @@
#define CONFIG_CLOCKS
#endif
-#if !defined(CONFIG_MTD_RAW_NAND) && \
- !defined(CONFIG_USE_NOR) && \
- !defined(CONFIG_USE_SPIFLASH)
-#endif
-
/* USB Configs */
#define CONFIG_USB_OHCI_NEW
#define CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS 15
-#ifndef CONFIG_DIRECT_NOR_BOOT
+#ifdef CONFIG_SPL_BUILD
/* defines for SPL */
#define CONFIG_SYS_SPL_MALLOC_START (CONFIG_SYS_TEXT_BASE - \
CONFIG_SYS_MALLOC_LEN)
@@ -247,12 +234,12 @@
/* additions for new relocation code, must added to all boards */
#define CONFIG_SYS_SDRAM_BASE 0xc0000000
-#ifdef CONFIG_DIRECT_NOR_BOOT
+#ifdef CONFIG_MTD_NOR_FLASH
#define CONFIG_SYS_INIT_SP_ADDR 0x8001ff00
#else
#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_SDRAM_BASE + 0x1000 - /* Fix this */ \
GENERATED_GBL_DATA_SIZE)
-#endif /* CONFIG_DIRECT_NOR_BOOT */
+#endif /* CONFIG_MTD_NOR_FLASH */
#include <asm/arch/hardware.h>
diff --git a/include/crypto/pkcs7_parser.h b/include/crypto/pkcs7_parser.h
index b8234da45a6..906033a90eb 100644
--- a/include/crypto/pkcs7_parser.h
+++ b/include/crypto/pkcs7_parser.h
@@ -10,7 +10,7 @@
#include <linux/oid_registry.h>
#include <crypto/pkcs7.h>
-#include "x509_parser.h"
+#include <crypto/x509_parser.h>
#define kenter(FMT, ...) \
pr_devel("==> %s("FMT")\n", __func__, ##__VA_ARGS__)
diff --git a/include/dt-bindings/dma/k3-udma.h b/include/dt-bindings/dma/k3-udma.h
deleted file mode 100644
index 670e1232b48..00000000000
--- a/include/dt-bindings/dma/k3-udma.h
+++ /dev/null
@@ -1,31 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com
- */
-
-#ifndef __DT_TI_UDMA_H
-#define __DT_TI_UDMA_H
-
-#define UDMA_TR_MODE 0
-#define UDMA_PKT_MODE 1
-
-#define UDMA_DIR_TX 0
-#define UDMA_DIR_RX 1
-
-#define PSIL_STATIC_TR_NONE 0
-#define PSIL_STATIC_TR_XY 1
-#define PSIL_STATIC_TR_MCAN 2
-
-#define UDMA_PDMA_TR_XY(id) \
- ti,psil-config##id { \
- linux,udma-mode = <UDMA_TR_MODE>; \
- statictr-type = <PSIL_STATIC_TR_XY>; \
- }
-
-#define UDMA_PDMA_PKT_XY(id) \
- ti,psil-config##id { \
- linux,udma-mode = <UDMA_PKT_MODE>; \
- statictr-type = <PSIL_STATIC_TR_XY>; \
- }
-
-#endif /* __DT_TI_UDMA_H */
diff --git a/include/efi_api.h b/include/efi_api.h
index 759d9118758..5744f6aed86 100644
--- a/include/efi_api.h
+++ b/include/efi_api.h
@@ -251,6 +251,8 @@ struct efi_rt_properties_table {
u32 runtime_services_supported;
};
+#define EFI_OPTIONAL_PTR 0x00000001
+
struct efi_runtime_services {
struct efi_table_hdr hdr;
efi_status_t (EFIAPI *get_time)(struct efi_time *time,
diff --git a/include/efi_loader.h b/include/efi_loader.h
index fc9344c7428..98944640bee 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -397,6 +397,9 @@ efi_status_t efi_root_node_register(void);
efi_status_t efi_initialize_system_table(void);
/* efi_runtime_detach() - detach unimplemented runtime functions */
void efi_runtime_detach(void);
+/* efi_convert_pointer() - convert pointer to virtual address */
+efi_status_t EFIAPI efi_convert_pointer(efi_uintn_t debug_disposition,
+ void **address);
/* Called by bootefi to make console interface available */
efi_status_t efi_console_register(void);
/* Called by bootefi to make all disk storage accessible as EFI objects */
@@ -765,14 +768,17 @@ struct efi_signature_store {
struct x509_certificate;
struct pkcs7_message;
-bool efi_signature_verify_cert(struct x509_certificate *cert,
- struct efi_signature_store *dbx);
-bool efi_signature_verify_signers(struct pkcs7_message *msg,
- struct efi_signature_store *dbx);
+bool efi_signature_lookup_digest(struct efi_image_regions *regs,
+ struct efi_signature_store *db);
+bool efi_signature_verify_one(struct efi_image_regions *regs,
+ struct pkcs7_message *msg,
+ struct efi_signature_store *db);
bool efi_signature_verify_with_sigdb(struct efi_image_regions *regs,
struct pkcs7_message *msg,
- struct efi_signature_store *db,
- struct x509_certificate **cert);
+ struct efi_signature_store *db,
+ struct efi_signature_store *dbx);
+bool efi_signature_check_signers(struct pkcs7_message *msg,
+ struct efi_signature_store *dbx);
efi_status_t efi_image_region_add(struct efi_image_regions *regs,
const void *start, const void *end,
@@ -786,6 +792,9 @@ bool efi_secure_boot_enabled(void);
bool efi_image_parse(void *efi, size_t len, struct efi_image_regions **regp,
WIN_CERTIFICATE **auth, size_t *auth_len);
+/* runtime implementation of memcpy() */
+void efi_memcpy_runtime(void *dest, const void *src, size_t n);
+
#else /* CONFIG_IS_ENABLED(EFI_LOADER) */
/* Without CONFIG_EFI_LOADER we don't have a runtime section, stub it out */
diff --git a/include/efi_variable.h b/include/efi_variable.h
new file mode 100644
index 00000000000..bc5985cfdb6
--- /dev/null
+++ b/include/efi_variable.h
@@ -0,0 +1,198 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2020, Heinrich Schuchardt <xypron.glpk@gmx.de>
+ */
+
+#ifndef _EFI_VARIABLE_H
+#define _EFI_VARIABLE_H
+
+#include <linux/bitops.h>
+
+#define EFI_VARIABLE_READ_ONLY BIT(31)
+
+/**
+ * efi_get_variable() - retrieve value of a UEFI variable
+ *
+ * @variable_name: name of the variable
+ * @vendor: vendor GUID
+ * @attributes: attributes of the variable
+ * @data_size: size of the buffer to which the variable value is copied
+ * @data: buffer to which the variable value is copied
+ * @timep: authentication time (seconds since start of epoch)
+ * Return: status code
+ */
+efi_status_t efi_get_variable_int(u16 *variable_name, const efi_guid_t *vendor,
+ u32 *attributes, efi_uintn_t *data_size,
+ void *data, u64 *timep);
+
+/**
+ * efi_set_variable() - set value of a UEFI variable
+ *
+ * @variable_name: name of the variable
+ * @vendor: vendor GUID
+ * @attributes: attributes of the variable
+ * @data_size: size of the buffer with the variable value
+ * @data: buffer with the variable value
+ * @ro_check: check the read only read only bit in attributes
+ * Return: status code
+ */
+efi_status_t efi_set_variable_int(u16 *variable_name, const efi_guid_t *vendor,
+ u32 attributes, efi_uintn_t data_size,
+ const void *data, bool ro_check);
+
+/**
+ * efi_get_next_variable_name_int() - enumerate the current variable names
+ *
+ * @variable_name_size: size of variable_name buffer in byte
+ * @variable_name: name of uefi variable's name in u16
+ * @vendor: vendor's guid
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
+ */
+efi_status_t efi_get_next_variable_name_int(efi_uintn_t *variable_name_size,
+ u16 *variable_name,
+ efi_guid_t *vendor);
+
+/**
+ * efi_query_variable_info_int() - get information about EFI variables
+ *
+ * This function implements the QueryVariableInfo() runtime service.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * @attributes: bitmask to select variables to be
+ * queried
+ * @maximum_variable_storage_size: maximum size of storage area for the
+ * selected variable types
+ * @remaining_variable_storage_size: remaining size of storage are for the
+ * selected variable types
+ * @maximum_variable_size: maximum size of a variable of the
+ * selected type
+ * Returns: status code
+ */
+efi_status_t efi_query_variable_info_int(u32 attributes,
+ u64 *maximum_variable_storage_size,
+ u64 *remaining_variable_storage_size,
+ u64 *maximum_variable_size);
+
+#define EFI_VAR_FILE_NAME "ubootefi.var"
+
+#define EFI_VAR_BUF_SIZE 0x4000
+
+#define EFI_VAR_FILE_MAGIC 0x0161566966456255 /* UbEfiVa, version 1 */
+
+/**
+ * struct efi_var_entry - UEFI variable file entry
+ *
+ * @length: length of enty, multiple of 8
+ * @attr: variable attributes
+ * @time: authentication time (seconds since start of epoch)
+ * @guid: vendor GUID
+ * @name: UTF16 variable name
+ */
+struct efi_var_entry {
+ u32 length;
+ u32 attr;
+ u64 time;
+ efi_guid_t guid;
+ u16 name[];
+};
+
+/**
+ * struct efi_var_file - file for storing UEFI variables
+ *
+ * @reserved: unused, may be overwritten by memory probing
+ * @magic: identifies file format
+ * @length: length including header
+ * @crc32: CRC32 without header
+ * @var: variables
+ */
+struct efi_var_file {
+ u64 reserved;
+ u64 magic;
+ u32 length;
+ u32 crc32;
+ struct efi_var_entry var[];
+};
+
+/**
+ * efi_var_to_file() - save non-volatile variables as file
+ *
+ * File ubootefi.var is created on the EFI system partion.
+ *
+ * Return: status code
+ */
+efi_status_t efi_var_to_file(void);
+
+/**
+ * efi_var_from_file() - read variables from file
+ *
+ * File ubootefi.var is read from the EFI system partitions and the variables
+ * stored in the file are created.
+ *
+ * In case the file does not exist yet or a variable cannot be set EFI_SUCCESS
+ * is returned.
+ *
+ * Return: status code
+ */
+efi_status_t efi_var_from_file(void);
+
+/**
+ * efi_var_mem_init() - set-up variable list
+ *
+ * Return: status code
+ */
+efi_status_t efi_var_mem_init(void);
+
+/**
+ * efi_var_mem_find() - find a variable in the list
+ *
+ * @guid: GUID of the variable
+ * @name: name of the variable
+ * @next: on exit pointer to the next variable after the found one
+ * Return: found variable
+ */
+struct efi_var_entry *efi_var_mem_find(const efi_guid_t *guid, const u16 *name,
+ struct efi_var_entry **next);
+
+/**
+ * efi_var_mem_del() - delete a variable from the list of variables
+ *
+ * @var: variable to delete
+ */
+void efi_var_mem_del(struct efi_var_entry *var);
+
+/**
+ * efi_var_mem_ins() - append a variable to the list of variables
+ *
+ * The variable is appended without checking if a variable of the same name
+ * already exists. The two data buffers are concatenated.
+ *
+ * @variable_name: variable name
+ * @vendor: GUID
+ * @attributes: variable attributes
+ * @size1: size of the first data buffer
+ * @data1: first data buffer
+ * @size2: size of the second data field
+ * @data2: second data buffer
+ * @time: time of authentication (as seconds since start of epoch)
+ * Result: status code
+ */
+efi_status_t efi_var_mem_ins(u16 *variable_name,
+ const efi_guid_t *vendor, u32 attributes,
+ const efi_uintn_t size1, const void *data1,
+ const efi_uintn_t size2, const void *data2,
+ const u64 time);
+
+/**
+ * efi_var_mem_free() - determine free memory for variables
+ *
+ * Return: maximum data size plus variable name size
+ */
+u64 efi_var_mem_free(void);
+
+#endif
diff --git a/include/linux/soc/ti/k3-navss-ringacc.h b/include/linux/soc/ti/k3-navss-ringacc.h
index 7b027f8bd4b..9176277ff0b 100644
--- a/include/linux/soc/ti/k3-navss-ringacc.h
+++ b/include/linux/soc/ti/k3-navss-ringacc.h
@@ -100,6 +100,10 @@ struct k3_nav_ring_cfg {
struct k3_nav_ring *k3_nav_ringacc_request_ring(struct k3_nav_ringacc *ringacc,
int id, u32 flags);
+int k3_nav_ringacc_request_rings_pair(struct k3_nav_ringacc *ringacc,
+ int fwd_id, int compl_id,
+ struct k3_nav_ring **fwd_ring,
+ struct k3_nav_ring **compl_ring);
/**
* k3_nav_ringacc_get_dev - get pointer on RA device
* @ringacc: pointer on RA
diff --git a/include/u-boot/rsa.h b/include/u-boot/rsa.h
index a0bae495f05..bed1c097c2c 100644
--- a/include/u-boot/rsa.h
+++ b/include/u-boot/rsa.h
@@ -112,6 +112,9 @@ int rsa_verify(struct image_sign_info *info,
const struct image_region region[], int region_count,
uint8_t *sig, uint sig_len);
+int rsa_verify_with_pkey(struct image_sign_info *info,
+ const void *hash, uint8_t *sig, uint sig_len);
+
int padding_pkcs_15_verify(struct image_sign_info *info,
uint8_t *msg, int msg_len,
const uint8_t *hash, int hash_len);
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
index 6c9df3a7676..4324694d480 100644
--- a/lib/efi_loader/Kconfig
+++ b/lib/efi_loader/Kconfig
@@ -27,6 +27,14 @@ config EFI_LOADER
if EFI_LOADER
+config EFI_VARIABLE_FILE_STORE
+ bool "Store non-volatile UEFI variables as file"
+ depends on FAT_WRITE
+ default y
+ help
+ Select tis option if you want non-volatile UEFI variables to be stored
+ as file /ubootefi.var on the EFI system partition.
+
config EFI_GET_TIME
bool "GetTime() runtime service"
depends on DM_RTC
diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile
index 57c7e66ea0e..f81ec8d2777 100644
--- a/lib/efi_loader/Makefile
+++ b/lib/efi_loader/Makefile
@@ -35,10 +35,13 @@ obj-y += efi_root_node.o
obj-y += efi_runtime.o
obj-y += efi_setup.o
obj-$(CONFIG_EFI_UNICODE_COLLATION_PROTOCOL2) += efi_unicode_collation.o
+obj-y += efi_var_common.o
+obj-y += efi_var_mem.o
ifeq ($(CONFIG_EFI_MM_COMM_TEE),y)
obj-y += efi_variable_tee.o
else
obj-y += efi_variable.o
+obj-y += efi_var_file.o
endif
obj-y += efi_watchdog.o
obj-$(CONFIG_LCD) += efi_gop.o
diff --git a/lib/efi_loader/efi_bootmgr.c b/lib/efi_loader/efi_bootmgr.c
index e268e9c4b82..e03198b57a8 100644
--- a/lib/efi_loader/efi_bootmgr.c
+++ b/lib/efi_loader/efi_bootmgr.c
@@ -12,6 +12,7 @@
#include <log.h>
#include <malloc.h>
#include <efi_loader.h>
+#include <efi_variable.h>
#include <asm/unaligned.h>
static const struct efi_boot_services *bs;
@@ -147,15 +148,14 @@ unsigned long efi_serialize_load_option(struct efi_load_option *lo, u8 **data)
static void *get_var(u16 *name, const efi_guid_t *vendor,
efi_uintn_t *size)
{
- efi_guid_t *v = (efi_guid_t *)vendor;
efi_status_t ret;
void *buf = NULL;
*size = 0;
- EFI_CALL(ret = rs->get_variable(name, v, NULL, size, buf));
+ ret = efi_get_variable_int(name, vendor, NULL, size, buf, NULL);
if (ret == EFI_BUFFER_TOO_SMALL) {
buf = malloc(*size);
- EFI_CALL(ret = rs->get_variable(name, v, NULL, size, buf));
+ ret = efi_get_variable_int(name, vendor, NULL, size, buf, NULL);
}
if (ret != EFI_SUCCESS) {
@@ -219,10 +219,9 @@ static efi_status_t try_load_entry(u16 n, efi_handle_t *handle)
attributes = EFI_VARIABLE_BOOTSERVICE_ACCESS |
EFI_VARIABLE_RUNTIME_ACCESS;
size = sizeof(n);
- ret = EFI_CALL(efi_set_variable(
- L"BootCurrent",
- (efi_guid_t *)&efi_global_variable_guid,
- attributes, size, &n));
+ ret = efi_set_variable_int(L"BootCurrent",
+ &efi_global_variable_guid,
+ attributes, size, &n, false);
if (ret != EFI_SUCCESS) {
if (EFI_CALL(efi_unload_image(*handle))
!= EFI_SUCCESS)
@@ -262,22 +261,19 @@ efi_status_t efi_bootmgr_load(efi_handle_t *handle)
rs = systab.runtime;
/* BootNext */
- bootnext = 0;
size = sizeof(bootnext);
- ret = EFI_CALL(efi_get_variable(L"BootNext",
- (efi_guid_t *)&efi_global_variable_guid,
- NULL, &size, &bootnext));
+ ret = efi_get_variable_int(L"BootNext",
+ &efi_global_variable_guid,
+ NULL, &size, &bootnext, NULL);
if (ret == EFI_SUCCESS || ret == EFI_BUFFER_TOO_SMALL) {
/* BootNext does exist here */
if (ret == EFI_BUFFER_TOO_SMALL || size != sizeof(u16))
log_err("BootNext must be 16-bit integer\n");
/* delete BootNext */
- ret = EFI_CALL(efi_set_variable(
- L"BootNext",
- (efi_guid_t *)&efi_global_variable_guid,
- EFI_VARIABLE_NON_VOLATILE, 0,
- &bootnext));
+ ret = efi_set_variable_int(L"BootNext",
+ &efi_global_variable_guid,
+ 0, 0, NULL, false);
/* load BootNext */
if (ret == EFI_SUCCESS) {
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index 1591ad83007..0b16554ba23 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -3459,6 +3459,8 @@ static efi_status_t efi_get_child_controllers(
* the buffer will be too large. But that does not harm.
*/
*number_of_children = 0;
+ if (!count)
+ return EFI_SUCCESS;
*child_handle_buffer = calloc(count, sizeof(efi_handle_t));
if (!*child_handle_buffer)
return EFI_OUT_OF_RESOURCES;
@@ -3536,10 +3538,12 @@ static efi_status_t EFIAPI efi_disconnect_controller(
number_of_children = 1;
child_handle_buffer = &child_handle;
} else {
- efi_get_child_controllers(efiobj,
- driver_image_handle,
- &number_of_children,
- &child_handle_buffer);
+ r = efi_get_child_controllers(efiobj,
+ driver_image_handle,
+ &number_of_children,
+ &child_handle_buffer);
+ if (r != EFI_SUCCESS)
+ return r;
}
/* Get the driver binding protocol */
diff --git a/lib/efi_loader/efi_image_loader.c b/lib/efi_loader/efi_image_loader.c
index 06a2ebdb908..fef0bb870c6 100644
--- a/lib/efi_loader/efi_image_loader.c
+++ b/lib/efi_loader/efi_image_loader.c
@@ -267,6 +267,8 @@ bool efi_image_parse(void *efi, size_t len, struct efi_image_regions **regp,
dos = (void *)efi;
nt = (void *)(efi + dos->e_lfanew);
+ authoff = 0;
+ authsz = 0;
/*
* Count maximum number of regions to be digested.
@@ -305,25 +307,36 @@ bool efi_image_parse(void *efi, size_t len, struct efi_image_regions **regp,
efi_image_region_add(regs,
&opt->DataDirectory[ctidx] + 1,
efi + opt->SizeOfHeaders, 0);
+
+ authoff = opt->DataDirectory[ctidx].VirtualAddress;
+ authsz = opt->DataDirectory[ctidx].Size;
}
bytes_hashed = opt->SizeOfHeaders;
align = opt->FileAlignment;
- authoff = opt->DataDirectory[ctidx].VirtualAddress;
- authsz = opt->DataDirectory[ctidx].Size;
} else if (nt->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
IMAGE_OPTIONAL_HEADER32 *opt = &nt->OptionalHeader;
+ /* Skip CheckSum */
efi_image_region_add(regs, efi, &opt->CheckSum, 0);
- efi_image_region_add(regs, &opt->Subsystem,
- &opt->DataDirectory[ctidx], 0);
- efi_image_region_add(regs, &opt->DataDirectory[ctidx] + 1,
- efi + opt->SizeOfHeaders, 0);
+ if (nt->OptionalHeader.NumberOfRvaAndSizes <= ctidx) {
+ efi_image_region_add(regs,
+ &opt->Subsystem,
+ efi + opt->SizeOfHeaders, 0);
+ } else {
+ /* Skip Certificates Table */
+ efi_image_region_add(regs, &opt->Subsystem,
+ &opt->DataDirectory[ctidx], 0);
+ efi_image_region_add(regs,
+ &opt->DataDirectory[ctidx] + 1,
+ efi + opt->SizeOfHeaders, 0);
+
+ authoff = opt->DataDirectory[ctidx].VirtualAddress;
+ authsz = opt->DataDirectory[ctidx].Size;
+ }
bytes_hashed = opt->SizeOfHeaders;
align = opt->FileAlignment;
- authoff = opt->DataDirectory[ctidx].VirtualAddress;
- authsz = opt->DataDirectory[ctidx].Size;
} else {
EFI_PRINT("%s: Invalid optional header magic %x\n", __func__,
nt->OptionalHeader.Magic);
@@ -369,7 +382,7 @@ bool efi_image_parse(void *efi, size_t len, struct efi_image_regions **regp,
/* 3. Extra data excluding Certificates Table */
if (bytes_hashed + authsz < len) {
- EFI_PRINT("extra data for hash: %lu\n",
+ EFI_PRINT("extra data for hash: %zu\n",
len - (bytes_hashed + authsz));
efi_image_region_add(regs, efi + bytes_hashed,
efi + len - authsz, 0);
@@ -435,16 +448,16 @@ static bool efi_image_unsigned_authenticate(struct efi_image_regions *regs)
}
/* try black-list first */
- if (efi_signature_verify_with_sigdb(regs, NULL, dbx, NULL)) {
- EFI_PRINT("Image is not signed and rejected by \"dbx\"\n");
+ if (efi_signature_lookup_digest(regs, dbx)) {
+ EFI_PRINT("Image is not signed and its digest found in \"dbx\"\n");
goto out;
}
/* try white-list */
- if (efi_signature_verify_with_sigdb(regs, NULL, db, NULL))
+ if (efi_signature_lookup_digest(regs, db))
ret = true;
else
- EFI_PRINT("Image is not signed and not found in \"db\" or \"dbx\"\n");
+ EFI_PRINT("Image is not signed and its digest not found in \"db\" or \"dbx\"\n");
out:
efi_sigstore_free(db);
@@ -481,11 +494,13 @@ static bool efi_image_authenticate(void *efi, size_t efi_size)
size_t wincerts_len;
struct pkcs7_message *msg = NULL;
struct efi_signature_store *db = NULL, *dbx = NULL;
- struct x509_certificate *cert = NULL;
void *new_efi = NULL;
- size_t new_efi_size;
+ u8 *auth, *wincerts_end;
+ size_t new_efi_size, auth_size;
bool ret = false;
+ debug("%s: Enter, %d\n", __func__, ret);
+
if (!efi_secure_boot_enabled())
return true;
@@ -531,61 +546,122 @@ static bool efi_image_authenticate(void *efi, size_t efi_size)
goto err;
}
- /* go through WIN_CERTIFICATE list */
- for (wincert = wincerts;
- (void *)wincert < (void *)wincerts + wincerts_len;
- wincert = (void *)wincert + ALIGN(wincert->dwLength, 8)) {
- if (wincert->dwLength < sizeof(*wincert)) {
- EFI_PRINT("%s: dwLength too small: %u < %zu\n",
- __func__, wincert->dwLength,
- sizeof(*wincert));
- goto err;
+ /*
+ * go through WIN_CERTIFICATE list
+ * NOTE:
+ * We may have multiple signatures either as WIN_CERTIFICATE's
+ * in PE header, or as pkcs7 SignerInfo's in SignedData.
+ * So the verification policy here is:
+ * - Success if, at least, one of signatures is verified
+ * - unless
+ * any of signatures is rejected explicitly, or
+ * none of digest algorithms are supported
+ */
+ for (wincert = wincerts, wincerts_end = (u8 *)wincerts + wincerts_len;
+ (u8 *)wincert < wincerts_end;
+ wincert = (WIN_CERTIFICATE *)
+ ((u8 *)wincert + ALIGN(wincert->dwLength, 8))) {
+ if ((u8 *)wincert + sizeof(*wincert) >= wincerts_end)
+ break;
+
+ if (wincert->dwLength <= sizeof(*wincert)) {
+ EFI_PRINT("dwLength too small: %u < %zu\n",
+ wincert->dwLength, sizeof(*wincert));
+ continue;
}
- msg = pkcs7_parse_message((void *)wincert + sizeof(*wincert),
- wincert->dwLength - sizeof(*wincert));
+
+ EFI_PRINT("WIN_CERTIFICATE_TYPE: 0x%x\n",
+ wincert->wCertificateType);
+
+ auth = (u8 *)wincert + sizeof(*wincert);
+ auth_size = wincert->dwLength - sizeof(*wincert);
+ if (wincert->wCertificateType == WIN_CERT_TYPE_EFI_GUID) {
+ if (auth + sizeof(efi_guid_t) >= wincerts_end)
+ break;
+
+ if (auth_size <= sizeof(efi_guid_t)) {
+ EFI_PRINT("dwLength too small: %u < %zu\n",
+ wincert->dwLength, sizeof(*wincert));
+ continue;
+ }
+ if (guidcmp(auth, &efi_guid_cert_type_pkcs7)) {
+ EFI_PRINT("Certificate type not supported: %pUl\n",
+ auth);
+ continue;
+ }
+
+ auth += sizeof(efi_guid_t);
+ auth_size -= sizeof(efi_guid_t);
+ } else if (wincert->wCertificateType
+ != WIN_CERT_TYPE_PKCS_SIGNED_DATA) {
+ EFI_PRINT("Certificate type not supported\n");
+ continue;
+ }
+
+ msg = pkcs7_parse_message(auth, auth_size);
if (IS_ERR(msg)) {
EFI_PRINT("Parsing image's signature failed\n");
msg = NULL;
- goto err;
+ continue;
}
+ /*
+ * NOTE:
+ * UEFI specification defines two signature types possible
+ * in signature database:
+ * a. x509 certificate, where a signature in image is
+ * a message digest encrypted by RSA public key
+ * (EFI_CERT_X509_GUID)
+ * b. bare hash value of message digest
+ * (EFI_CERT_SHAxxx_GUID)
+ *
+ * efi_signature_verify() handles case (a), while
+ * efi_signature_lookup_digest() handles case (b).
+ *
+ * There is a third type:
+ * c. message digest of a certificate
+ * (EFI_CERT_X509_SHAAxxx_GUID)
+ * This type of signature is used only in revocation list
+ * (dbx) and handled as part of efi_signatgure_verify().
+ */
/* try black-list first */
- if (efi_signature_verify_with_sigdb(regs, msg, dbx, NULL)) {
+ if (efi_signature_verify_one(regs, msg, dbx)) {
EFI_PRINT("Signature was rejected by \"dbx\"\n");
goto err;
}
- if (!efi_signature_verify_signers(msg, dbx)) {
- EFI_PRINT("Signer was rejected by \"dbx\"\n");
+ if (!efi_signature_check_signers(msg, dbx)) {
+ EFI_PRINT("Signer(s) in \"dbx\"\n");
goto err;
- } else {
- ret = true;
}
- /* try white-list */
- if (!efi_signature_verify_with_sigdb(regs, msg, db, &cert)) {
- EFI_PRINT("Verifying signature with \"db\" failed\n");
+ if (efi_signature_lookup_digest(regs, dbx)) {
+ EFI_PRINT("Image's digest was found in \"dbx\"\n");
goto err;
- } else {
- ret = true;
}
- if (!efi_signature_verify_cert(cert, dbx)) {
- EFI_PRINT("Certificate was rejected by \"dbx\"\n");
- goto err;
- } else {
- ret = true;
- }
+ /* try white-list */
+ if (efi_signature_verify_with_sigdb(regs, msg, db, dbx))
+ continue;
+
+ debug("Signature was not verified by \"db\"\n");
+
+ if (efi_signature_lookup_digest(regs, db))
+ continue;
+
+ debug("Image's digest was not found in \"db\" or \"dbx\"\n");
+ goto err;
}
+ ret = true;
err:
- x509_free_certificate(cert);
efi_sigstore_free(db);
efi_sigstore_free(dbx);
pkcs7_free_message(msg);
free(regs);
free(new_efi);
+ debug("%s: Exit, %d\n", __func__, ret);
return ret;
}
#else
diff --git a/lib/efi_loader/efi_runtime.c b/lib/efi_loader/efi_runtime.c
index c0bd99b8674..91a45514488 100644
--- a/lib/efi_loader/efi_runtime.c
+++ b/lib/efi_loader/efi_runtime.c
@@ -121,6 +121,8 @@ efi_status_t efi_init_runtime_supported(void)
rt_table->version = EFI_RT_PROPERTIES_TABLE_VERSION;
rt_table->length = sizeof(struct efi_rt_properties_table);
rt_table->runtime_services_supported =
+ EFI_RT_SUPPORTED_GET_VARIABLE |
+ EFI_RT_SUPPORTED_GET_NEXT_VARIABLE_NAME |
EFI_RT_SUPPORTED_SET_VIRTUAL_ADDRESS_MAP |
EFI_RT_SUPPORTED_CONVERT_POINTER;
@@ -138,6 +140,25 @@ efi_status_t efi_init_runtime_supported(void)
}
/**
+ * efi_memcpy_runtime() - copy memory area
+ *
+ * At runtime memcpy() is not available.
+ *
+ * @dest: destination buffer
+ * @src: source buffer
+ * @n: number of bytes to copy
+ * Return: pointer to destination buffer
+ */
+void __efi_runtime efi_memcpy_runtime(void *dest, const void *src, size_t n)
+{
+ u8 *d = dest;
+ const u8 *s = src;
+
+ for (; n; --n)
+ *d++ = *s++;
+}
+
+/**
* efi_update_table_header_crc32() - Update crc32 in table header
*
* @table: EFI table
@@ -496,15 +517,13 @@ static __efi_runtime efi_status_t EFIAPI efi_convert_pointer_runtime(
* @address: pointer to be converted
* Return: status code
*/
-static __efi_runtime efi_status_t EFIAPI efi_convert_pointer(
- efi_uintn_t debug_disposition, void **address)
+__efi_runtime efi_status_t EFIAPI
+efi_convert_pointer(efi_uintn_t debug_disposition, void **address)
{
- efi_physical_addr_t addr = (uintptr_t)*address;
+ efi_physical_addr_t addr;
efi_uintn_t i;
efi_status_t ret = EFI_NOT_FOUND;
- EFI_ENTRY("%zu %p", debug_disposition, address);
-
if (!efi_virtmap) {
ret = EFI_UNSUPPORTED;
goto out;
@@ -514,7 +533,14 @@ static __efi_runtime efi_status_t EFIAPI efi_convert_pointer(
ret = EFI_INVALID_PARAMETER;
goto out;
}
+ if (!*address) {
+ if (debug_disposition & EFI_OPTIONAL_PTR)
+ return EFI_SUCCESS;
+ else
+ return EFI_INVALID_PARAMETER;
+ }
+ addr = (uintptr_t)*address;
for (i = 0; i < efi_descriptor_count; i++) {
struct efi_mem_desc *map = (void *)efi_virtmap +
(efi_descriptor_size * i);
@@ -532,7 +558,7 @@ static __efi_runtime efi_status_t EFIAPI efi_convert_pointer(
}
out:
- return EFI_EXIT(ret);
+ return ret;
}
static __efi_runtime void efi_relocate_runtime_table(ulong offset)
diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c
index a3b05a4a9b1..6196c0a06cd 100644
--- a/lib/efi_loader/efi_setup.c
+++ b/lib/efi_loader/efi_setup.c
@@ -8,6 +8,7 @@
#include <common.h>
#include <bootm.h>
#include <efi_loader.h>
+#include <efi_variable.h>
#define OBJ_LIST_NOT_INITIALIZED 1
@@ -40,12 +41,13 @@ static efi_status_t efi_init_platform_lang(void)
* Variable PlatformLangCodes defines the language codes that the
* machine can support.
*/
- ret = EFI_CALL(efi_set_variable(L"PlatformLangCodes",
- &efi_global_variable_guid,
- EFI_VARIABLE_BOOTSERVICE_ACCESS |
- EFI_VARIABLE_RUNTIME_ACCESS,
- sizeof(CONFIG_EFI_PLATFORM_LANG_CODES),
- CONFIG_EFI_PLATFORM_LANG_CODES));
+ ret = efi_set_variable_int(L"PlatformLangCodes",
+ &efi_global_variable_guid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ EFI_VARIABLE_RUNTIME_ACCESS |
+ EFI_VARIABLE_READ_ONLY,
+ sizeof(CONFIG_EFI_PLATFORM_LANG_CODES),
+ CONFIG_EFI_PLATFORM_LANG_CODES, false);
if (ret != EFI_SUCCESS)
goto out;
@@ -53,9 +55,9 @@ static efi_status_t efi_init_platform_lang(void)
* Variable PlatformLang defines the language that the machine has been
* configured for.
*/
- ret = EFI_CALL(efi_get_variable(L"PlatformLang",
- &efi_global_variable_guid,
- NULL, &data_size, &pos));
+ ret = efi_get_variable_int(L"PlatformLang",
+ &efi_global_variable_guid,
+ NULL, &data_size, &pos, NULL);
if (ret == EFI_BUFFER_TOO_SMALL) {
/* The variable is already set. Do not change it. */
ret = EFI_SUCCESS;
@@ -70,12 +72,12 @@ static efi_status_t efi_init_platform_lang(void)
if (pos)
*pos = 0;
- ret = EFI_CALL(efi_set_variable(L"PlatformLang",
- &efi_global_variable_guid,
- EFI_VARIABLE_NON_VOLATILE |
- EFI_VARIABLE_BOOTSERVICE_ACCESS |
- EFI_VARIABLE_RUNTIME_ACCESS,
- 1 + strlen(lang), lang));
+ ret = efi_set_variable_int(L"PlatformLang",
+ &efi_global_variable_guid,
+ EFI_VARIABLE_NON_VOLATILE |
+ EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ EFI_VARIABLE_RUNTIME_ACCESS,
+ 1 + strlen(lang), lang, false);
out:
if (ret != EFI_SUCCESS)
printf("EFI: cannot initialize platform language settings\n");
@@ -96,13 +98,13 @@ static efi_status_t efi_init_secure_boot(void)
};
efi_status_t ret;
- /* TODO: read-only */
- ret = EFI_CALL(efi_set_variable(L"SignatureSupport",
- &efi_global_variable_guid,
- EFI_VARIABLE_BOOTSERVICE_ACCESS
- | EFI_VARIABLE_RUNTIME_ACCESS,
- sizeof(signature_types),
- &signature_types));
+ ret = efi_set_variable_int(L"SignatureSupport",
+ &efi_global_variable_guid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ EFI_VARIABLE_RUNTIME_ACCESS |
+ EFI_VARIABLE_READ_ONLY,
+ sizeof(signature_types),
+ &signature_types, false);
if (ret != EFI_SUCCESS)
printf("EFI: cannot initialize SignatureSupport variable\n");
@@ -160,12 +162,13 @@ efi_status_t efi_init_obj_list(void)
goto out;
/* Indicate supported features */
- ret = EFI_CALL(efi_set_variable(L"OsIndicationsSupported",
- &efi_global_variable_guid,
- EFI_VARIABLE_BOOTSERVICE_ACCESS |
- EFI_VARIABLE_RUNTIME_ACCESS,
- sizeof(os_indications_supported),
- &os_indications_supported));
+ ret = efi_set_variable_int(L"OsIndicationsSupported",
+ &efi_global_variable_guid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ EFI_VARIABLE_RUNTIME_ACCESS |
+ EFI_VARIABLE_READ_ONLY,
+ sizeof(os_indications_supported),
+ &os_indications_supported, false);
if (ret != EFI_SUCCESS)
goto out;
diff --git a/lib/efi_loader/efi_signature.c b/lib/efi_loader/efi_signature.c
index e05c471c61c..fc0314e6d48 100644
--- a/lib/efi_loader/efi_signature.c
+++ b/lib/efi_loader/efi_signature.c
@@ -28,7 +28,8 @@ const efi_guid_t efi_guid_cert_type_pkcs7 = EFI_CERT_TYPE_PKCS7_GUID;
/**
* efi_hash_regions - calculate a hash value
- * @regs: List of regions
+ * @regs: Array of regions
+ * @count: Number of regions
* @hash: Pointer to a pointer to buffer holding a hash value
* @size: Size of buffer to be returned
*
@@ -36,18 +37,20 @@ const efi_guid_t efi_guid_cert_type_pkcs7 = EFI_CERT_TYPE_PKCS7_GUID;
*
* Return: true on success, false on error
*/
-static bool efi_hash_regions(struct efi_image_regions *regs, void **hash,
- size_t *size)
+static bool efi_hash_regions(struct image_region *regs, int count,
+ void **hash, size_t *size)
{
- *size = 0;
- *hash = calloc(1, SHA256_SUM_LEN);
if (!*hash) {
- EFI_PRINT("Out of memory\n");
- return false;
+ *hash = calloc(1, SHA256_SUM_LEN);
+ if (!*hash) {
+ EFI_PRINT("Out of memory\n");
+ return false;
+ }
}
- *size = SHA256_SUM_LEN;
+ if (size)
+ *size = SHA256_SUM_LEN;
- hash_calculate("sha256", regs->reg, regs->num, *hash);
+ hash_calculate("sha256", regs, count, *hash);
#ifdef DEBUG
EFI_PRINT("hash calculated:\n");
print_hex_dump(" ", DUMP_PREFIX_OFFSET, 16, 1,
@@ -72,26 +75,10 @@ static bool efi_hash_msg_content(struct pkcs7_message *msg, void **hash,
{
struct image_region regtmp;
- *size = 0;
- *hash = calloc(1, SHA256_SUM_LEN);
- if (!*hash) {
- EFI_PRINT("Out of memory\n");
- free(msg);
- return false;
- }
- *size = SHA256_SUM_LEN;
-
regtmp.data = msg->data;
regtmp.size = msg->data_len;
- hash_calculate("sha256", &regtmp, 1, *hash);
-#ifdef DEBUG
- EFI_PRINT("hash calculated based on contentInfo:\n");
- print_hex_dump(" ", DUMP_PREFIX_OFFSET, 16, 1,
- *hash, SHA256_SUM_LEN, false);
-#endif
-
- return true;
+ return efi_hash_regions(&regtmp, 1, hash, size);
}
/**
@@ -169,9 +156,10 @@ static bool efi_signature_verify(struct efi_image_regions *regs,
false);
#endif
/* against contentInfo first */
+ hash = NULL;
if ((msg->data && efi_hash_msg_content(msg, &hash, &size)) ||
/* for signed image */
- efi_hash_regions(regs, &hash, &size)) {
+ efi_hash_regions(regs->reg, regs->num, &hash, &size)) {
/* for authenticated variable */
if (ps_info->msgdigest_len != size ||
memcmp(hash, ps_info->msgdigest, size)) {
@@ -210,55 +198,43 @@ out:
}
/**
- * efi_signature_verify_with_list - verify a signature with signature list
- * @regs: List of regions to be authenticated
- * @msg: Signature
- * @signed_info: Pointer to PKCS7's signed_info
- * @siglist: Signature list for certificates
- * @valid_cert: x509 certificate that verifies this signature
+ * efi_signature_lookup_digest - search for an image's digest in sigdb
+ * @regs: List of regions to be authenticated
+ * @db: Signature database for trusted certificates
*
- * Signature pointed to by @signed_info against image pointed to by @regs
- * is verified by signature list pointed to by @siglist.
- * Signature database is a simple concatenation of one or more
- * signature list(s).
+ * A message digest of image pointed to by @regs is calculated and
+ * its hash value is compared to entries in signature database pointed
+ * to by @db.
*
- * Return: true if signature is verified, false if not
+ * Return: true if found, false if not
*/
-static
-bool efi_signature_verify_with_list(struct efi_image_regions *regs,
- struct pkcs7_message *msg,
- struct pkcs7_signed_info *signed_info,
- struct efi_signature_store *siglist,
- struct x509_certificate **valid_cert)
+bool efi_signature_lookup_digest(struct efi_image_regions *regs,
+ struct efi_signature_store *db)
{
- struct x509_certificate *cert;
+ struct efi_signature_store *siglist;
struct efi_sig_data *sig_data;
- bool verified = false;
+ void *hash = NULL;
+ size_t size = 0;
+ bool found = false;
- EFI_PRINT("%s: Enter, %p, %p, %p, %p\n", __func__,
- regs, signed_info, siglist, valid_cert);
+ EFI_PRINT("%s: Enter, %p, %p\n", __func__, regs, db);
- if (!signed_info) {
- void *hash;
- size_t size;
+ if (!regs || !db || !db->sig_data_list)
+ goto out;
- EFI_PRINT("%s: unsigned image\n", __func__);
- /*
- * verify based on calculated hash value
- * TODO: support other hash algorithms
- */
+ for (siglist = db; siglist; siglist = siglist->next) {
+ /* TODO: support other hash algorithms */
if (guidcmp(&siglist->sig_type, &efi_guid_sha256)) {
EFI_PRINT("Digest algorithm is not supported: %pUl\n",
&siglist->sig_type);
- goto out;
+ break;
}
- if (!efi_hash_regions(regs, &hash, &size)) {
- EFI_PRINT("Digesting unsigned image failed\n");
- goto out;
+ if (!efi_hash_regions(regs->reg, regs->num, &hash, &size)) {
+ EFI_PRINT("Digesting an image failed\n");
+ break;
}
- /* go through the list */
for (sig_data = siglist->sig_data_list; sig_data;
sig_data = sig_data->next) {
#ifdef DEBUG
@@ -266,18 +242,52 @@ bool efi_signature_verify_with_list(struct efi_image_regions *regs,
print_hex_dump(" ", DUMP_PREFIX_OFFSET, 16, 1,
sig_data->data, sig_data->size, false);
#endif
- if ((sig_data->size == size) &&
+ if (sig_data->size == size &&
!memcmp(sig_data->data, hash, size)) {
- verified = true;
+ found = true;
free(hash);
goto out;
}
}
+
free(hash);
- goto out;
+ hash = NULL;
}
- EFI_PRINT("%s: signed image\n", __func__);
+out:
+ EFI_PRINT("%s: Exit, found: %d\n", __func__, found);
+ return found;
+}
+
+/**
+ * efi_signature_verify_with_list - verify a signature with signature list
+ * @regs: List of regions to be authenticated
+ * @msg: Signature
+ * @signed_info: Pointer to PKCS7's signed_info
+ * @siglist: Signature list for certificates
+ * @valid_cert: x509 certificate that verifies this signature
+ *
+ * Signature pointed to by @signed_info against image pointed to by @regs
+ * is verified by signature list pointed to by @siglist.
+ * Signature database is a simple concatenation of one or more
+ * signature list(s).
+ *
+ * Return: true if signature is verified, false if not
+ */
+static
+bool efi_signature_verify_with_list(struct efi_image_regions *regs,
+ struct pkcs7_message *msg,
+ struct pkcs7_signed_info *signed_info,
+ struct efi_signature_store *siglist,
+ struct x509_certificate **valid_cert)
+{
+ struct x509_certificate *cert;
+ struct efi_sig_data *sig_data;
+ bool verified = false;
+
+ EFI_PRINT("%s: Enter, %p, %p, %p, %p\n", __func__,
+ regs, signed_info, siglist, valid_cert);
+
if (guidcmp(&siglist->sig_type, &efi_guid_cert_x509)) {
EFI_PRINT("Signature type is not supported: %pUl\n",
&siglist->sig_type);
@@ -313,211 +323,222 @@ out:
}
/**
- * efi_signature_verify_with_sigdb - verify a signature with db
- * @regs: List of regions to be authenticated
- * @msg: Signature
- * @db: Signature database for trusted certificates
- * @cert: x509 certificate that verifies this signature
+ * efi_signature_check_revocation - check revocation with dbx
+ * @sinfo: Signer's info
+ * @cert: x509 certificate
+ * @dbx: Revocation signature database
*
- * Signature pointed to by @msg against image pointed to by @regs
- * is verified by signature database pointed to by @db.
+ * Search revocation signature database pointed to by @dbx and find
+ * an entry matching to certificate pointed to by @cert.
*
- * Return: true if signature is verified, false if not
+ * While this entry contains revocation time, we don't support timestamp
+ * protocol at this time and any image will be unconditionally revoked
+ * when this match occurs.
+ *
+ * Return: true if check passed, false otherwise.
*/
-bool efi_signature_verify_with_sigdb(struct efi_image_regions *regs,
- struct pkcs7_message *msg,
- struct efi_signature_store *db,
- struct x509_certificate **cert)
+static bool efi_signature_check_revocation(struct pkcs7_signed_info *sinfo,
+ struct x509_certificate *cert,
+ struct efi_signature_store *dbx)
{
- struct pkcs7_signed_info *info;
struct efi_signature_store *siglist;
- bool verified = false;
-
- EFI_PRINT("%s: Enter, %p, %p, %p, %p\n", __func__, regs, msg, db, cert);
+ struct efi_sig_data *sig_data;
+ struct image_region reg[1];
+ void *hash = NULL;
+ size_t size = 0;
+ time64_t revoc_time;
+ bool revoked = false;
- if (!db)
- goto out;
+ EFI_PRINT("%s: Enter, %p, %p, %p\n", __func__, sinfo, cert, dbx);
- if (!db->sig_data_list)
+ if (!sinfo || !cert || !dbx || !dbx->sig_data_list)
goto out;
- /* for unsigned image */
- if (!msg) {
- EFI_PRINT("%s: Verify unsigned image with db\n", __func__);
- for (siglist = db; siglist; siglist = siglist->next)
- if (efi_signature_verify_with_list(regs, NULL, NULL,
- siglist, cert)) {
- verified = true;
- goto out;
- }
-
- goto out;
- }
+ EFI_PRINT("Checking revocation against %s\n", cert->subject);
+ for (siglist = dbx; siglist; siglist = siglist->next) {
+ if (guidcmp(&siglist->sig_type, &efi_guid_cert_x509_sha256))
+ continue;
- /* for signed image or variable */
- EFI_PRINT("%s: Verify signed image with db\n", __func__);
- for (info = msg->signed_infos; info; info = info->next) {
- EFI_PRINT("Signed Info: digest algo: %s, pkey algo: %s\n",
- info->sig->hash_algo, info->sig->pkey_algo);
+ /* calculate hash of TBSCertificate */
+ reg[0].data = cert->tbs;
+ reg[0].size = cert->tbs_size;
+ if (!efi_hash_regions(reg, 1, &hash, &size))
+ goto out;
- for (siglist = db; siglist; siglist = siglist->next) {
- if (efi_signature_verify_with_list(regs, msg, info,
- siglist, cert)) {
- verified = true;
- goto out;
+ for (sig_data = siglist->sig_data_list; sig_data;
+ sig_data = sig_data->next) {
+ /*
+ * struct efi_cert_x509_sha256 {
+ * u8 tbs_hash[256/8];
+ * time64_t revocation_time;
+ * };
+ */
+#ifdef DEBUG
+ if (sig_data->size >= size) {
+ EFI_PRINT("hash in db:\n");
+ print_hex_dump(" ", DUMP_PREFIX_OFFSET,
+ 16, 1,
+ sig_data->data, size, false);
}
+#endif
+ if ((sig_data->size < size + sizeof(time64_t)) ||
+ memcmp(sig_data->data, hash, size))
+ continue;
+
+ memcpy(&revoc_time, sig_data->data + size,
+ sizeof(revoc_time));
+ EFI_PRINT("revocation time: 0x%llx\n", revoc_time);
+ /*
+ * TODO: compare signing timestamp in sinfo
+ * with revocation time
+ */
+
+ revoked = true;
+ free(hash);
+ goto out;
}
+ free(hash);
+ hash = NULL;
}
-
out:
- EFI_PRINT("%s: Exit, verified: %d\n", __func__, verified);
- return verified;
+ EFI_PRINT("%s: Exit, revoked: %d\n", __func__, revoked);
+ return !revoked;
}
/**
- * efi_search_siglist - search signature list for a certificate
- * @cert: x509 certificate
- * @siglist: Signature list
- * @revoc_time: Pointer to buffer for revocation time
+ * efi_signature_verify_one - verify signatures with database
+ * @regs: List of regions to be authenticated
+ * @msg: Signature
+ * @db: Signature database
*
- * Search signature list pointed to by @siglist and find a certificate
- * pointed to by @cert.
- * If found, revocation time that is specified in signature database is
- * returned in @revoc_time.
+ * All the signature pointed to by @msg against image pointed to by @regs
+ * will be verified by signature database pointed to by @db.
*
- * Return: true if certificate is found, false if not
+ * Return: true if verification for one of signatures passed, false
+ * otherwise
*/
-static bool efi_search_siglist(struct x509_certificate *cert,
- struct efi_signature_store *siglist,
- time64_t *revoc_time)
+bool efi_signature_verify_one(struct efi_image_regions *regs,
+ struct pkcs7_message *msg,
+ struct efi_signature_store *db)
{
- struct image_region reg[1];
- void *hash = NULL, *msg = NULL;
- struct efi_sig_data *sig_data;
- bool found = false;
-
- /* can be null */
- if (!siglist->sig_data_list)
- return false;
+ struct pkcs7_signed_info *sinfo;
+ struct efi_signature_store *siglist;
+ struct x509_certificate *cert;
+ bool verified = false;
- if (guidcmp(&siglist->sig_type, &efi_guid_cert_x509_sha256)) {
- /* TODO: other hash algos */
- EFI_PRINT("Certificate's digest type is not supported: %pUl\n",
- &siglist->sig_type);
- goto out;
- }
+ EFI_PRINT("%s: Enter, %p, %p, %p\n", __func__, regs, msg, db);
- /* calculate hash of TBSCertificate */
- msg = calloc(1, SHA256_SUM_LEN);
- if (!msg) {
- EFI_PRINT("Out of memory\n");
+ if (!db)
goto out;
- }
- hash = calloc(1, SHA256_SUM_LEN);
- if (!hash) {
- EFI_PRINT("Out of memory\n");
+ if (!db->sig_data_list)
goto out;
- }
- reg[0].data = cert->tbs;
- reg[0].size = cert->tbs_size;
- hash_calculate("sha256", reg, 1, msg);
+ EFI_PRINT("%s: Verify signed image with db\n", __func__);
+ for (sinfo = msg->signed_infos; sinfo; sinfo = sinfo->next) {
+ EFI_PRINT("Signed Info: digest algo: %s, pkey algo: %s\n",
+ sinfo->sig->hash_algo, sinfo->sig->pkey_algo);
- /* go through signature list */
- for (sig_data = siglist->sig_data_list; sig_data;
- sig_data = sig_data->next) {
- /*
- * struct efi_cert_x509_sha256 {
- * u8 tbs_hash[256/8];
- * time64_t revocation_time;
- * };
- */
- if ((sig_data->size == SHA256_SUM_LEN) &&
- !memcmp(sig_data->data, hash, SHA256_SUM_LEN)) {
- memcpy(revoc_time, sig_data->data + SHA256_SUM_LEN,
- sizeof(*revoc_time));
- found = true;
- goto out;
- }
+ for (siglist = db; siglist; siglist = siglist->next)
+ if (efi_signature_verify_with_list(regs, msg, sinfo,
+ siglist, &cert)) {
+ verified = true;
+ goto out;
+ }
+ EFI_PRINT("Valid certificate not in \"db\"\n");
}
out:
- free(hash);
- free(msg);
-
- return found;
+ EFI_PRINT("%s: Exit, verified: %d\n", __func__, verified);
+ return verified;
}
/**
- * efi_signature_verify_cert - verify a certificate with dbx
- * @cert: x509 certificate
- * @dbx: Signature database
+ * efi_signature_verify_with_sigdb - verify signatures with db and dbx
+ * @regs: List of regions to be authenticated
+ * @msg: Signature
+ * @db: Signature database for trusted certificates
+ * @dbx: Revocation signature database
*
- * Search signature database pointed to by @dbx and find a certificate
- * pointed to by @cert.
- * This function is expected to be used against "dbx".
+ * All the signature pointed to by @msg against image pointed to by @regs
+ * will be verified by signature database pointed to by @db and @dbx.
*
- * Return: true if a certificate is not rejected, false otherwise.
+ * Return: true if verification for all signatures passed, false otherwise
*/
-bool efi_signature_verify_cert(struct x509_certificate *cert,
- struct efi_signature_store *dbx)
+bool efi_signature_verify_with_sigdb(struct efi_image_regions *regs,
+ struct pkcs7_message *msg,
+ struct efi_signature_store *db,
+ struct efi_signature_store *dbx)
{
+ struct pkcs7_signed_info *info;
struct efi_signature_store *siglist;
- time64_t revoc_time;
- bool found = false;
+ struct x509_certificate *cert;
+ bool verified = false;
- EFI_PRINT("%s: Enter, %p, %p\n", __func__, dbx, cert);
+ EFI_PRINT("%s: Enter, %p, %p, %p, %p\n", __func__, regs, msg, db, dbx);
- if (!cert)
- return false;
+ if (!regs || !msg || !db || !db->sig_data_list)
+ goto out;
- for (siglist = dbx; siglist; siglist = siglist->next) {
- if (efi_search_siglist(cert, siglist, &revoc_time)) {
- /* TODO */
- /* compare signing time with revocation time */
+ for (info = msg->signed_infos; info; info = info->next) {
+ EFI_PRINT("Signed Info: digest algo: %s, pkey algo: %s\n",
+ info->sig->hash_algo, info->sig->pkey_algo);
- found = true;
- break;
+ for (siglist = db; siglist; siglist = siglist->next) {
+ if (efi_signature_verify_with_list(regs, msg, info,
+ siglist, &cert))
+ break;
+ }
+ if (!siglist) {
+ EFI_PRINT("Valid certificate not in \"db\"\n");
+ goto out;
}
+
+ if (!dbx || efi_signature_check_revocation(info, cert, dbx))
+ continue;
+
+ EFI_PRINT("Certificate in \"dbx\"\n");
+ goto out;
}
+ verified = true;
- EFI_PRINT("%s: Exit, verified: %d\n", __func__, !found);
- return !found;
+out:
+ EFI_PRINT("%s: Exit, verified: %d\n", __func__, verified);
+ return verified;
}
/**
- * efi_signature_verify_signers - verify signers' certificates with dbx
+ * efi_signature_check_signers - check revocation against all signers with dbx
* @msg: Signature
- * @dbx: Signature database
+ * @dbx: Revocation signature database
*
- * Determine if any of signers' certificates in @msg may be verified
- * by any of certificates in signature database pointed to by @dbx.
- * This function is expected to be used against "dbx".
+ * Determine if none of signers' certificates in @msg are revoked
+ * by signature database pointed to by @dbx.
*
- * Return: true if none of certificates is rejected, false otherwise.
+ * Return: true if all signers passed, false otherwise.
*/
-bool efi_signature_verify_signers(struct pkcs7_message *msg,
- struct efi_signature_store *dbx)
+bool efi_signature_check_signers(struct pkcs7_message *msg,
+ struct efi_signature_store *dbx)
{
- struct pkcs7_signed_info *info;
- bool found = false;
+ struct pkcs7_signed_info *sinfo;
+ bool revoked = false;
EFI_PRINT("%s: Enter, %p, %p\n", __func__, msg, dbx);
- if (!msg)
+ if (!msg || !dbx)
goto out;
- for (info = msg->signed_infos; info; info = info->next) {
- if (info->signer &&
- !efi_signature_verify_cert(info->signer, dbx)) {
- found = true;
- goto out;
+ for (sinfo = msg->signed_infos; sinfo; sinfo = sinfo->next) {
+ if (sinfo->signer &&
+ !efi_signature_check_revocation(sinfo, sinfo->signer,
+ dbx)) {
+ revoked = true;
+ break;
}
}
out:
- EFI_PRINT("%s: Exit, verified: %d\n", __func__, !found);
- return !found;
+ EFI_PRINT("%s: Exit, revoked: %d\n", __func__, revoked);
+ return !revoked;
}
/**
diff --git a/lib/efi_loader/efi_var_common.c b/lib/efi_loader/efi_var_common.c
new file mode 100644
index 00000000000..1e2be1135b9
--- /dev/null
+++ b/lib/efi_loader/efi_var_common.c
@@ -0,0 +1,140 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * UEFI runtime variable services
+ *
+ * Copyright (c) 2020, Heinrich Schuchardt <xypron.glpk@gmx.de>
+ */
+
+#include <common.h>
+#include <efi_loader.h>
+#include <efi_variable.h>
+
+/**
+ * efi_efi_get_variable() - retrieve value of a UEFI variable
+ *
+ * This function implements the GetVariable runtime service.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * @variable_name: name of the variable
+ * @vendor: vendor GUID
+ * @attributes: attributes of the variable
+ * @data_size: size of the buffer to which the variable value is copied
+ * @data: buffer to which the variable value is copied
+ * Return: status code
+ */
+efi_status_t EFIAPI efi_get_variable(u16 *variable_name,
+ const efi_guid_t *vendor, u32 *attributes,
+ efi_uintn_t *data_size, void *data)
+{
+ efi_status_t ret;
+
+ EFI_ENTRY("\"%ls\" %pUl %p %p %p", variable_name, vendor, attributes,
+ data_size, data);
+
+ ret = efi_get_variable_int(variable_name, vendor, attributes,
+ data_size, data, NULL);
+
+ /* Remove EFI_VARIABLE_READ_ONLY flag */
+ if (attributes)
+ *attributes &= EFI_VARIABLE_MASK;
+
+ return EFI_EXIT(ret);
+}
+
+/**
+ * efi_set_variable() - set value of a UEFI variable
+ *
+ * This function implements the SetVariable runtime service.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * @variable_name: name of the variable
+ * @vendor: vendor GUID
+ * @attributes: attributes of the variable
+ * @data_size: size of the buffer with the variable value
+ * @data: buffer with the variable value
+ * Return: status code
+ */
+efi_status_t EFIAPI efi_set_variable(u16 *variable_name,
+ const efi_guid_t *vendor, u32 attributes,
+ efi_uintn_t data_size, const void *data)
+{
+ efi_status_t ret;
+
+ EFI_ENTRY("\"%ls\" %pUl %x %zu %p", variable_name, vendor, attributes,
+ data_size, data);
+
+ /* Make sure that the EFI_VARIABLE_READ_ONLY flag is not set */
+ if (attributes & ~(u32)EFI_VARIABLE_MASK)
+ ret = EFI_INVALID_PARAMETER;
+ else
+ ret = efi_set_variable_int(variable_name, vendor, attributes,
+ data_size, data, true);
+
+ return EFI_EXIT(ret);
+}
+
+/**
+ * efi_get_next_variable_name() - enumerate the current variable names
+ *
+ * @variable_name_size: size of variable_name buffer in byte
+ * @variable_name: name of uefi variable's name in u16
+ * @vendor: vendor's guid
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
+ */
+efi_status_t EFIAPI efi_get_next_variable_name(efi_uintn_t *variable_name_size,
+ u16 *variable_name,
+ efi_guid_t *vendor)
+{
+ efi_status_t ret;
+
+ EFI_ENTRY("%p \"%ls\" %pUl", variable_name_size, variable_name, vendor);
+
+ ret = efi_get_next_variable_name_int(variable_name_size, variable_name,
+ vendor);
+
+ return EFI_EXIT(ret);
+}
+
+/**
+ * efi_query_variable_info() - get information about EFI variables
+ *
+ * This function implements the QueryVariableInfo() runtime service.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * @attributes: bitmask to select variables to be
+ * queried
+ * @maximum_variable_storage_size: maximum size of storage area for the
+ * selected variable types
+ * @remaining_variable_storage_size: remaining size of storage are for the
+ * selected variable types
+ * @maximum_variable_size: maximum size of a variable of the
+ * selected type
+ * Returns: status code
+ */
+efi_status_t EFIAPI efi_query_variable_info(
+ u32 attributes, u64 *maximum_variable_storage_size,
+ u64 *remaining_variable_storage_size,
+ u64 *maximum_variable_size)
+{
+ efi_status_t ret;
+
+ EFI_ENTRY("%x %p %p %p", attributes, maximum_variable_storage_size,
+ remaining_variable_storage_size, maximum_variable_size);
+
+ ret = efi_query_variable_info_int(attributes,
+ maximum_variable_storage_size,
+ remaining_variable_storage_size,
+ maximum_variable_size);
+
+ return EFI_EXIT(ret);
+}
diff --git a/lib/efi_loader/efi_var_file.c b/lib/efi_loader/efi_var_file.c
new file mode 100644
index 00000000000..880c279aefb
--- /dev/null
+++ b/lib/efi_loader/efi_var_file.c
@@ -0,0 +1,239 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * File interface for UEFI variables
+ *
+ * Copyright (c) 2020, Heinrich Schuchardt
+ */
+
+#define LOG_CATEGORY LOGC_EFI
+
+#include <common.h>
+#include <charset.h>
+#include <fs.h>
+#include <log.h>
+#include <malloc.h>
+#include <mapmem.h>
+#include <efi_loader.h>
+#include <efi_variable.h>
+#include <u-boot/crc.h>
+
+#define PART_STR_LEN 10
+
+/**
+ * efi_set_blk_dev_to_system_partition() - select EFI system partition
+ *
+ * Set the EFI system partition as current block device.
+ *
+ * Return: status code
+ */
+static efi_status_t __maybe_unused efi_set_blk_dev_to_system_partition(void)
+{
+ char part_str[PART_STR_LEN];
+ int r;
+
+ if (!efi_system_partition.if_type) {
+ log_err("No EFI system partition\n");
+ return EFI_DEVICE_ERROR;
+ }
+ snprintf(part_str, PART_STR_LEN, "%u:%u",
+ efi_system_partition.devnum, efi_system_partition.part);
+ r = fs_set_blk_dev(blk_get_if_type_name(efi_system_partition.if_type),
+ part_str, FS_TYPE_ANY);
+ if (r) {
+ log_err("Cannot read EFI system partition\n");
+ return EFI_DEVICE_ERROR;
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ * efi_var_collect() - collect non-volatile variables in buffer
+ *
+ * A buffer is allocated and filled with all non-volatile variables in a
+ * format ready to be written to disk.
+ *
+ * @bufp: pointer to pointer of buffer with collected variables
+ * @lenp: pointer to length of buffer
+ * Return: status code
+ */
+static efi_status_t __maybe_unused efi_var_collect(struct efi_var_file **bufp,
+ loff_t *lenp)
+{
+ size_t len = EFI_VAR_BUF_SIZE;
+ struct efi_var_file *buf;
+ struct efi_var_entry *var, *old_var;
+ size_t old_var_name_length = 2;
+
+ *bufp = NULL; /* Avoid double free() */
+ buf = calloc(1, len);
+ if (!buf)
+ return EFI_OUT_OF_RESOURCES;
+ var = buf->var;
+ old_var = var;
+ for (;;) {
+ efi_uintn_t data_length, var_name_length;
+ u8 *data;
+ efi_status_t ret;
+
+ if ((uintptr_t)buf + len <=
+ (uintptr_t)var->name + old_var_name_length)
+ return EFI_BUFFER_TOO_SMALL;
+
+ var_name_length = (uintptr_t)buf + len - (uintptr_t)var->name;
+ memcpy(var->name, old_var->name, old_var_name_length);
+ guidcpy(&var->guid, &old_var->guid);
+ ret = efi_get_next_variable_name_int(
+ &var_name_length, var->name, &var->guid);
+ if (ret == EFI_NOT_FOUND)
+ break;
+ if (ret != EFI_SUCCESS) {
+ free(buf);
+ return ret;
+ }
+ old_var_name_length = var_name_length;
+ old_var = var;
+
+ data = (u8 *)var->name + old_var_name_length;
+ data_length = (uintptr_t)buf + len - (uintptr_t)data;
+ ret = efi_get_variable_int(var->name, &var->guid,
+ &var->attr, &data_length, data,
+ &var->time);
+ if (ret != EFI_SUCCESS) {
+ free(buf);
+ return ret;
+ }
+ if (!(var->attr & EFI_VARIABLE_NON_VOLATILE))
+ continue;
+ var->length = data_length;
+ var = (struct efi_var_entry *)
+ ALIGN((uintptr_t)data + data_length, 8);
+ }
+
+ buf->reserved = 0;
+ buf->magic = EFI_VAR_FILE_MAGIC;
+ len = (uintptr_t)var - (uintptr_t)buf;
+ buf->crc32 = crc32(0, (u8 *)buf->var,
+ len - sizeof(struct efi_var_file));
+ buf->length = len;
+ *bufp = buf;
+ *lenp = len;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ * efi_var_to_file() - save non-volatile variables as file
+ *
+ * File ubootefi.var is created on the EFI system partion.
+ *
+ * Return: status code
+ */
+efi_status_t efi_var_to_file(void)
+{
+#ifdef CONFIG_EFI_VARIABLE_FILE_STORE
+ efi_status_t ret;
+ struct efi_var_file *buf;
+ loff_t len;
+ loff_t actlen;
+ int r;
+
+ ret = efi_var_collect(&buf, &len);
+ if (ret != EFI_SUCCESS)
+ goto error;
+
+ ret = efi_set_blk_dev_to_system_partition();
+ if (ret != EFI_SUCCESS)
+ goto error;
+
+ r = fs_write(EFI_VAR_FILE_NAME, map_to_sysmem(buf), 0, len, &actlen);
+ if (r || len != actlen)
+ ret = EFI_DEVICE_ERROR;
+
+error:
+ if (ret != EFI_SUCCESS)
+ log_err("Failed to persist EFI variables\n");
+ free(buf);
+ return ret;
+#else
+ return EFI_SUCCESS;
+#endif
+}
+
+/**
+ * efi_var_restore() - restore EFI variables from buffer
+ *
+ * @buf: buffer
+ * Return: status code
+ */
+static efi_status_t __maybe_unused efi_var_restore(struct efi_var_file *buf)
+{
+ struct efi_var_entry *var, *last_var;
+ efi_status_t ret;
+
+ if (buf->reserved || buf->magic != EFI_VAR_FILE_MAGIC ||
+ buf->crc32 != crc32(0, (u8 *)buf->var,
+ buf->length - sizeof(struct efi_var_file))) {
+ log_err("Invalid EFI variables file\n");
+ return EFI_INVALID_PARAMETER;
+ }
+
+ var = buf->var;
+ last_var = (struct efi_var_entry *)((u8 *)buf + buf->length);
+ while (var < last_var) {
+ u16 *data = var->name + u16_strlen(var->name) + 1;
+
+ if (var->attr & EFI_VARIABLE_NON_VOLATILE && var->length) {
+ ret = efi_var_mem_ins(var->name, &var->guid, var->attr,
+ var->length, data, 0, NULL,
+ var->time);
+ if (ret != EFI_SUCCESS)
+ log_err("Failed to set EFI variable %ls\n",
+ var->name);
+ }
+ var = (struct efi_var_entry *)
+ ALIGN((uintptr_t)data + var->length, 8);
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ * efi_var_from_file() - read variables from file
+ *
+ * File ubootefi.var is read from the EFI system partitions and the variables
+ * stored in the file are created.
+ *
+ * In case the file does not exist yet or a variable cannot be set EFI_SUCCESS
+ * is returned.
+ *
+ * Return: status code
+ */
+efi_status_t efi_var_from_file(void)
+{
+#ifdef CONFIG_EFI_VARIABLE_FILE_STORE
+ struct efi_var_file *buf;
+ loff_t len;
+ efi_status_t ret;
+ int r;
+
+ buf = calloc(1, EFI_VAR_BUF_SIZE);
+ if (!buf) {
+ log_err("Out of memory\n");
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ ret = efi_set_blk_dev_to_system_partition();
+ if (ret != EFI_SUCCESS)
+ goto error;
+ r = fs_read(EFI_VAR_FILE_NAME, map_to_sysmem(buf), 0, EFI_VAR_BUF_SIZE,
+ &len);
+ if (r || len < sizeof(struct efi_var_file)) {
+ log_err("Failed to load EFI variables\n");
+ goto error;
+ }
+ if (buf->length != len || efi_var_restore(buf) != EFI_SUCCESS)
+ log_err("Invalid EFI variables file\n");
+error:
+ free(buf);
+#endif
+ return EFI_SUCCESS;
+}
diff --git a/lib/efi_loader/efi_var_mem.c b/lib/efi_loader/efi_var_mem.c
new file mode 100644
index 00000000000..7a2dba7dc26
--- /dev/null
+++ b/lib/efi_loader/efi_var_mem.c
@@ -0,0 +1,266 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * File interface for UEFI variables
+ *
+ * Copyright (c) 2020, Heinrich Schuchardt
+ */
+
+#include <common.h>
+#include <efi_loader.h>
+#include <efi_variable.h>
+#include <u-boot/crc.h>
+
+static struct efi_var_file __efi_runtime_data *efi_var_buf;
+static struct efi_var_entry __efi_runtime_data *efi_current_var;
+
+/**
+ * efi_var_mem_compare() - compare GUID and name with a variable
+ *
+ * @var: variable to compare
+ * @guid: GUID to compare
+ * @name: variable name to compare
+ * @next: pointer to next variable
+ * Return: true if match
+ */
+static bool __efi_runtime
+efi_var_mem_compare(struct efi_var_entry *var, const efi_guid_t *guid,
+ const u16 *name, struct efi_var_entry **next)
+{
+ int i;
+ u8 *guid1, *guid2;
+ const u16 *data, *var_name;
+ bool match = true;
+
+ for (guid1 = (u8 *)&var->guid, guid2 = (u8 *)guid, i = 0;
+ i < sizeof(efi_guid_t) && match; ++i)
+ match = (guid1[i] == guid2[i]);
+
+ for (data = var->name, var_name = name;; ++data, ++var_name) {
+ if (match)
+ match = (*data == *var_name);
+ if (!*data)
+ break;
+ }
+
+ ++data;
+
+ if (next)
+ *next = (struct efi_var_entry *)
+ ALIGN((uintptr_t)data + var->length, 8);
+
+ if (match)
+ efi_current_var = var;
+
+ return match;
+}
+
+struct efi_var_entry __efi_runtime
+*efi_var_mem_find(const efi_guid_t *guid, const u16 *name,
+ struct efi_var_entry **next)
+{
+ struct efi_var_entry *var, *last;
+
+ last = (struct efi_var_entry *)
+ ((uintptr_t)efi_var_buf + efi_var_buf->length);
+
+ if (!*name) {
+ if (next) {
+ *next = efi_var_buf->var;
+ if (*next >= last)
+ *next = NULL;
+ }
+ return NULL;
+ }
+ if (efi_current_var &&
+ efi_var_mem_compare(efi_current_var, guid, name, next)) {
+ if (next && *next >= last)
+ *next = NULL;
+ return efi_current_var;
+ }
+
+ var = efi_var_buf->var;
+ if (var < last) {
+ for (; var;) {
+ struct efi_var_entry *pos;
+ bool match;
+
+ match = efi_var_mem_compare(var, guid, name, &pos);
+ if (pos >= last)
+ pos = NULL;
+ if (match) {
+ if (next)
+ *next = pos;
+ return var;
+ }
+ var = pos;
+ }
+ }
+ if (next)
+ *next = NULL;
+ return NULL;
+}
+
+void __efi_runtime efi_var_mem_del(struct efi_var_entry *var)
+{
+ u16 *data;
+ struct efi_var_entry *next, *last;
+
+ if (!var)
+ return;
+
+ last = (struct efi_var_entry *)
+ ((uintptr_t)efi_var_buf + efi_var_buf->length);
+ if (var <= efi_current_var)
+ efi_current_var = NULL;
+
+ for (data = var->name; *data; ++data)
+ ;
+ ++data;
+ next = (struct efi_var_entry *)
+ ALIGN((uintptr_t)data + var->length, 8);
+ efi_var_buf->length -= (uintptr_t)next - (uintptr_t)var;
+
+ memmove(var, next, (uintptr_t)last - (uintptr_t)next);
+ efi_var_buf->crc32 = crc32(0, (u8 *)efi_var_buf->var,
+ efi_var_buf->length -
+ sizeof(struct efi_var_file));
+}
+
+efi_status_t __efi_runtime efi_var_mem_ins(
+ u16 *variable_name,
+ const efi_guid_t *vendor, u32 attributes,
+ const efi_uintn_t size1, const void *data1,
+ const efi_uintn_t size2, const void *data2,
+ const u64 time)
+{
+ u16 *data;
+ struct efi_var_entry *var;
+ u32 var_name_len;
+
+ var = (struct efi_var_entry *)
+ ((uintptr_t)efi_var_buf + efi_var_buf->length);
+ for (var_name_len = 0; variable_name[var_name_len]; ++var_name_len)
+ ;
+ ++var_name_len;
+ data = var->name + var_name_len;
+
+ if ((uintptr_t)data - (uintptr_t)efi_var_buf + size1 + size2 >
+ EFI_VAR_BUF_SIZE)
+ return EFI_OUT_OF_RESOURCES;
+
+ var->attr = attributes;
+ var->length = size1 + size2;
+ var->time = time;
+
+ efi_memcpy_runtime(&var->guid, vendor, sizeof(efi_guid_t));
+ efi_memcpy_runtime(var->name, variable_name,
+ sizeof(u16) * var_name_len);
+ efi_memcpy_runtime(data, data1, size1);
+ efi_memcpy_runtime((u8 *)data + size1, data2, size2);
+
+ var = (struct efi_var_entry *)
+ ALIGN((uintptr_t)data + var->length, 8);
+ efi_var_buf->length = (uintptr_t)var - (uintptr_t)efi_var_buf;
+ efi_var_buf->crc32 = crc32(0, (u8 *)efi_var_buf->var,
+ efi_var_buf->length -
+ sizeof(struct efi_var_file));
+
+ return EFI_SUCCESS;
+}
+
+u64 __efi_runtime efi_var_mem_free(void)
+{
+ return EFI_VAR_BUF_SIZE - efi_var_buf->length -
+ sizeof(struct efi_var_entry);
+}
+
+/**
+ * efi_var_mem_bs_del() - delete boot service only variables
+ */
+static void efi_var_mem_bs_del(void)
+{
+ struct efi_var_entry *var = efi_var_buf->var;
+
+ for (;;) {
+ struct efi_var_entry *last;
+
+ last = (struct efi_var_entry *)
+ ((uintptr_t)efi_var_buf + efi_var_buf->length);
+ if (var >= last)
+ break;
+ if (var->attr & EFI_VARIABLE_RUNTIME_ACCESS) {
+ u16 *data;
+
+ /* skip variable */
+ for (data = var->name; *data; ++data)
+ ;
+ ++data;
+ var = (struct efi_var_entry *)
+ ALIGN((uintptr_t)data + var->length, 8);
+ } else {
+ /* delete variable */
+ efi_var_mem_del(var);
+ }
+ }
+}
+
+/**
+ * efi_var_mem_notify_exit_boot_services() - ExitBootService callback
+ *
+ * @event: callback event
+ * @context: callback context
+ */
+static void EFIAPI __efi_runtime
+efi_var_mem_notify_exit_boot_services(struct efi_event *event, void *context)
+{
+ EFI_ENTRY("%p, %p", event, context);
+
+ /* Delete boot service only variables */
+ efi_var_mem_bs_del();
+
+ EFI_EXIT(EFI_SUCCESS);
+}
+
+/**
+ * efi_var_mem_notify_exit_boot_services() - SetVirtualMemoryMap callback
+ *
+ * @event: callback event
+ * @context: callback context
+ */
+static void EFIAPI __efi_runtime
+efi_var_mem_notify_virtual_address_map(struct efi_event *event, void *context)
+{
+ efi_convert_pointer(0, (void **)&efi_var_buf);
+}
+
+efi_status_t efi_var_mem_init(void)
+{
+ u64 memory;
+ efi_status_t ret;
+ struct efi_event *event;
+
+ ret = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES,
+ EFI_RUNTIME_SERVICES_DATA,
+ efi_size_in_pages(EFI_VAR_BUF_SIZE),
+ &memory);
+ if (ret != EFI_SUCCESS)
+ return ret;
+ efi_var_buf = (struct efi_var_file *)(uintptr_t)memory;
+ memset(efi_var_buf, 0, EFI_VAR_BUF_SIZE);
+ efi_var_buf->magic = EFI_VAR_FILE_MAGIC;
+ efi_var_buf->length = (uintptr_t)efi_var_buf->var -
+ (uintptr_t)efi_var_buf;
+ /* crc32 for 0 bytes = 0 */
+
+ ret = efi_create_event(EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_CALLBACK,
+ efi_var_mem_notify_exit_boot_services, NULL,
+ NULL, &event);
+ if (ret != EFI_SUCCESS)
+ return ret;
+ ret = efi_create_event(EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE, TPL_CALLBACK,
+ efi_var_mem_notify_virtual_address_map, NULL,
+ NULL, &event);
+ if (ret != EFI_SUCCESS)
+ return ret;
+ return ret;
+}
diff --git a/lib/efi_loader/efi_variable.c b/lib/efi_loader/efi_variable.c
index efaba869ef2..eab5f005daa 100644
--- a/lib/efi_loader/efi_variable.c
+++ b/lib/efi_loader/efi_variable.c
@@ -7,6 +7,7 @@
#include <common.h>
#include <efi_loader.h>
+#include <efi_variable.h>
#include <env.h>
#include <env_internal.h>
#include <hexdump.h>
@@ -15,7 +16,6 @@
#include <search.h>
#include <uuid.h>
#include <crypto/pkcs7_parser.h>
-#include <linux/bitops.h>
#include <linux/compat.h>
#include <u-boot/crc.h>
@@ -30,160 +30,6 @@ static bool efi_secure_boot;
static enum efi_secure_mode efi_secure_mode;
static u8 efi_vendor_keys;
-#define READ_ONLY BIT(31)
-
-static efi_status_t efi_get_variable_common(u16 *variable_name,
- const efi_guid_t *vendor,
- u32 *attributes,
- efi_uintn_t *data_size, void *data,
- u64 *timep);
-
-static efi_status_t efi_set_variable_common(u16 *variable_name,
- const efi_guid_t *vendor,
- u32 attributes,
- efi_uintn_t data_size,
- const void *data,
- bool ro_check);
-
-/*
- * Mapping between EFI variables and u-boot variables:
- *
- * efi_$guid_$varname = {attributes}(type)value
- *
- * For example:
- *
- * efi_8be4df61-93ca-11d2-aa0d-00e098032b8c_OsIndicationsSupported=
- * "{ro,boot,run}(blob)0000000000000000"
- * efi_8be4df61-93ca-11d2-aa0d-00e098032b8c_BootOrder=
- * "(blob)00010000"
- *
- * The attributes are a comma separated list of these possible
- * attributes:
- *
- * + ro - read-only
- * + boot - boot-services access
- * + run - runtime access
- *
- * NOTE: with current implementation, no variables are available after
- * ExitBootServices, and all are persisted (if possible).
- *
- * If not specified, the attributes default to "{boot}".
- *
- * The required type is one of:
- *
- * + utf8 - raw utf8 string
- * + blob - arbitrary length hex string
- *
- * Maybe a utf16 type would be useful to for a string value to be auto
- * converted to utf16?
- */
-
-#define PREFIX_LEN (strlen("efi_xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx_"))
-
-/**
- * efi_to_native() - convert the UEFI variable name and vendor GUID to U-Boot
- * variable name
- *
- * The U-Boot variable name is a concatenation of prefix 'efi', the hexstring
- * encoded vendor GUID, and the UTF-8 encoded UEFI variable name separated by
- * underscores, e.g. 'efi_8be4df61-93ca-11d2-aa0d-00e098032b8c_BootOrder'.
- *
- * @native: pointer to pointer to U-Boot variable name
- * @variable_name: UEFI variable name
- * @vendor: vendor GUID
- * Return: status code
- */
-static efi_status_t efi_to_native(char **native, const u16 *variable_name,
- const efi_guid_t *vendor)
-{
- size_t len;
- char *pos;
-
- len = PREFIX_LEN + utf16_utf8_strlen(variable_name) + 1;
- *native = malloc(len);
- if (!*native)
- return EFI_OUT_OF_RESOURCES;
-
- pos = *native;
- pos += sprintf(pos, "efi_%pUl_", vendor);
- utf16_utf8_strcpy(&pos, variable_name);
-
- return EFI_SUCCESS;
-}
-
-/**
- * prefix() - skip over prefix
- *
- * Skip over a prefix string.
- *
- * @str: string with prefix
- * @prefix: prefix string
- * Return: string without prefix, or NULL if prefix not found
- */
-static const char *prefix(const char *str, const char *prefix)
-{
- size_t n = strlen(prefix);
- if (!strncmp(prefix, str, n))
- return str + n;
- return NULL;
-}
-
-/**
- * parse_attr() - decode attributes part of variable value
- *
- * Convert the string encoded attributes of a UEFI variable to a bit mask.
- * TODO: Several attributes are not supported.
- *
- * @str: value of U-Boot variable
- * @attrp: pointer to UEFI attributes
- * @timep: pointer to time attribute
- * Return: pointer to remainder of U-Boot variable value
- */
-static const char *parse_attr(const char *str, u32 *attrp, u64 *timep)
-{
- u32 attr = 0;
- char sep = '{';
-
- if (*str != '{') {
- *attrp = EFI_VARIABLE_BOOTSERVICE_ACCESS;
- return str;
- }
-
- while (*str == sep) {
- const char *s;
-
- str++;
-
- if ((s = prefix(str, "ro"))) {
- attr |= READ_ONLY;
- } else if ((s = prefix(str, "nv"))) {
- attr |= EFI_VARIABLE_NON_VOLATILE;
- } else if ((s = prefix(str, "boot"))) {
- attr |= EFI_VARIABLE_BOOTSERVICE_ACCESS;
- } else if ((s = prefix(str, "run"))) {
- attr |= EFI_VARIABLE_RUNTIME_ACCESS;
- } else if ((s = prefix(str, "time="))) {
- attr |= EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
- hex2bin((u8 *)timep, s, sizeof(*timep));
- s += sizeof(*timep) * 2;
- } else if (*str == '}') {
- break;
- } else {
- printf("invalid attribute: %s\n", str);
- break;
- }
-
- str = s;
- sep = ',';
- }
-
- str++;
-
- *attrp = attr;
-
- return str;
-}
-
/**
* efi_set_secure_state - modify secure boot state variables
* @secure_boot: value of SecureBoot
@@ -198,34 +44,40 @@ static const char *parse_attr(const char *str, u32 *attrp, u64 *timep)
static efi_status_t efi_set_secure_state(u8 secure_boot, u8 setup_mode,
u8 audit_mode, u8 deployed_mode)
{
- u32 attributes;
efi_status_t ret;
+ const u32 attributes_ro = EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ EFI_VARIABLE_RUNTIME_ACCESS |
+ EFI_VARIABLE_READ_ONLY;
+ const u32 attributes_rw = EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ EFI_VARIABLE_RUNTIME_ACCESS;
- attributes = EFI_VARIABLE_BOOTSERVICE_ACCESS |
- EFI_VARIABLE_RUNTIME_ACCESS |
- READ_ONLY;
- ret = efi_set_variable_common(L"SecureBoot", &efi_global_variable_guid,
- attributes, sizeof(secure_boot),
- &secure_boot, false);
+ efi_secure_boot = secure_boot;
+
+ ret = efi_set_variable_int(L"SecureBoot", &efi_global_variable_guid,
+ attributes_ro, sizeof(secure_boot),
+ &secure_boot, false);
if (ret != EFI_SUCCESS)
goto err;
- ret = efi_set_variable_common(L"SetupMode", &efi_global_variable_guid,
- attributes, sizeof(setup_mode),
- &setup_mode, false);
+ ret = efi_set_variable_int(L"SetupMode", &efi_global_variable_guid,
+ attributes_ro, sizeof(setup_mode),
+ &setup_mode, false);
if (ret != EFI_SUCCESS)
goto err;
- ret = efi_set_variable_common(L"AuditMode", &efi_global_variable_guid,
- attributes, sizeof(audit_mode),
- &audit_mode, false);
+ ret = efi_set_variable_int(L"AuditMode", &efi_global_variable_guid,
+ audit_mode || setup_mode ?
+ attributes_ro : attributes_rw,
+ sizeof(audit_mode), &audit_mode, false);
if (ret != EFI_SUCCESS)
goto err;
- ret = efi_set_variable_common(L"DeployedMode",
- &efi_global_variable_guid, attributes,
- sizeof(deployed_mode), &deployed_mode,
- false);
+ ret = efi_set_variable_int(L"DeployedMode",
+ &efi_global_variable_guid,
+ audit_mode || deployed_mode || setup_mode ?
+ attributes_ro : attributes_rw,
+ sizeof(deployed_mode), &deployed_mode,
+ false);
err:
return ret;
}
@@ -235,7 +87,7 @@ err:
* @mode: new state
*
* Depending on @mode, secure boot related variables are updated.
- * Those variables are *read-only* for users, efi_set_variable_common()
+ * Those variables are *read-only* for users, efi_set_variable_int()
* is called here.
*
* Return: status code
@@ -251,27 +103,21 @@ static efi_status_t efi_transfer_secure_state(enum efi_secure_mode mode)
ret = efi_set_secure_state(1, 0, 0, 1);
if (ret != EFI_SUCCESS)
goto err;
-
- efi_secure_boot = true;
} else if (mode == EFI_MODE_AUDIT) {
- ret = efi_set_variable_common(L"PK", &efi_global_variable_guid,
- EFI_VARIABLE_BOOTSERVICE_ACCESS |
- EFI_VARIABLE_RUNTIME_ACCESS,
- 0, NULL, false);
+ ret = efi_set_variable_int(L"PK", &efi_global_variable_guid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ EFI_VARIABLE_RUNTIME_ACCESS,
+ 0, NULL, false);
if (ret != EFI_SUCCESS)
goto err;
ret = efi_set_secure_state(0, 1, 1, 0);
if (ret != EFI_SUCCESS)
goto err;
-
- efi_secure_boot = true;
} else if (mode == EFI_MODE_USER) {
ret = efi_set_secure_state(1, 0, 0, 0);
if (ret != EFI_SUCCESS)
goto err;
-
- efi_secure_boot = true;
} else if (mode == EFI_MODE_SETUP) {
ret = efi_set_secure_state(0, 1, 0, 0);
if (ret != EFI_SUCCESS)
@@ -297,45 +143,29 @@ err:
*/
static efi_status_t efi_init_secure_state(void)
{
- enum efi_secure_mode mode;
- efi_uintn_t size;
+ enum efi_secure_mode mode = EFI_MODE_SETUP;
+ efi_uintn_t size = 0;
efi_status_t ret;
- /*
- * TODO:
- * Since there is currently no "platform-specific" installation
- * method of Platform Key, we can't say if VendorKeys is 0 or 1
- * precisely.
- */
-
- size = 0;
- ret = efi_get_variable_common(L"PK", &efi_global_variable_guid,
- NULL, &size, NULL, NULL);
+ ret = efi_get_variable_int(L"PK", &efi_global_variable_guid,
+ NULL, &size, NULL, NULL);
if (ret == EFI_BUFFER_TOO_SMALL) {
if (IS_ENABLED(CONFIG_EFI_SECURE_BOOT))
mode = EFI_MODE_USER;
- else
- mode = EFI_MODE_SETUP;
-
- efi_vendor_keys = 0;
- } else if (ret == EFI_NOT_FOUND) {
- mode = EFI_MODE_SETUP;
- efi_vendor_keys = 1;
- } else {
- goto err;
}
ret = efi_transfer_secure_state(mode);
- if (ret == EFI_SUCCESS)
- ret = efi_set_variable_common(L"VendorKeys",
- &efi_global_variable_guid,
- EFI_VARIABLE_BOOTSERVICE_ACCESS |
- EFI_VARIABLE_RUNTIME_ACCESS |
- READ_ONLY,
- sizeof(efi_vendor_keys),
- &efi_vendor_keys, false);
+ if (ret != EFI_SUCCESS)
+ return ret;
-err:
+ /* As we do not provide vendor keys this variable is always 0. */
+ ret = efi_set_variable_int(L"VendorKeys",
+ &efi_global_variable_guid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ EFI_VARIABLE_RUNTIME_ACCESS |
+ EFI_VARIABLE_READ_ONLY,
+ sizeof(efi_vendor_keys),
+ &efi_vendor_keys, false);
return ret;
}
@@ -599,346 +429,115 @@ static efi_status_t efi_variable_authenticate(u16 *variable,
}
#endif /* CONFIG_EFI_SECURE_BOOT */
-static efi_status_t efi_get_variable_common(u16 *variable_name,
- const efi_guid_t *vendor,
- u32 *attributes,
- efi_uintn_t *data_size, void *data,
- u64 *timep)
+efi_status_t __efi_runtime
+efi_get_variable_int(u16 *variable_name, const efi_guid_t *vendor,
+ u32 *attributes, efi_uintn_t *data_size, void *data,
+ u64 *timep)
{
- char *native_name;
- efi_status_t ret;
- unsigned long in_size;
- const char *val = NULL, *s;
- u64 time = 0;
- u32 attr;
+ efi_uintn_t old_size;
+ struct efi_var_entry *var;
+ u16 *pdata;
if (!variable_name || !vendor || !data_size)
return EFI_INVALID_PARAMETER;
-
- ret = efi_to_native(&native_name, variable_name, vendor);
- if (ret)
- return ret;
-
- EFI_PRINT("get '%s'\n", native_name);
-
- val = env_get(native_name);
- free(native_name);
- if (!val)
+ var = efi_var_mem_find(vendor, variable_name, NULL);
+ if (!var)
return EFI_NOT_FOUND;
- val = parse_attr(val, &attr, &time);
-
+ if (attributes)
+ *attributes = var->attr;
if (timep)
- *timep = time;
-
- in_size = *data_size;
-
- if ((s = prefix(val, "(blob)"))) {
- size_t len = strlen(s);
-
- /* number of hexadecimal digits must be even */
- if (len & 1)
- return EFI_DEVICE_ERROR;
-
- /* two characters per byte: */
- len /= 2;
- *data_size = len;
-
- if (in_size < len) {
- ret = EFI_BUFFER_TOO_SMALL;
- goto out;
- }
-
- if (!data) {
- EFI_PRINT("Variable with no data shouldn't exist.\n");
- return EFI_INVALID_PARAMETER;
- }
-
- if (hex2bin(data, s, len))
- return EFI_DEVICE_ERROR;
-
- EFI_PRINT("got value: \"%s\"\n", s);
- } else if ((s = prefix(val, "(utf8)"))) {
- unsigned len = strlen(s) + 1;
-
- *data_size = len;
-
- if (in_size < len) {
- ret = EFI_BUFFER_TOO_SMALL;
- goto out;
- }
+ *timep = var->time;
- if (!data) {
- EFI_PRINT("Variable with no data shouldn't exist.\n");
- return EFI_INVALID_PARAMETER;
- }
-
- memcpy(data, s, len);
- ((char *)data)[len] = '\0';
-
- EFI_PRINT("got value: \"%s\"\n", (char *)data);
- } else {
- EFI_PRINT("invalid value: '%s'\n", val);
- return EFI_DEVICE_ERROR;
- }
-
-out:
- if (attributes)
- *attributes = attr & EFI_VARIABLE_MASK;
+ old_size = *data_size;
+ *data_size = var->length;
+ if (old_size < var->length)
+ return EFI_BUFFER_TOO_SMALL;
- return ret;
-}
+ if (!data)
+ return EFI_INVALID_PARAMETER;
-/**
- * efi_efi_get_variable() - retrieve value of a UEFI variable
- *
- * This function implements the GetVariable runtime service.
- *
- * See the Unified Extensible Firmware Interface (UEFI) specification for
- * details.
- *
- * @variable_name: name of the variable
- * @vendor: vendor GUID
- * @attributes: attributes of the variable
- * @data_size: size of the buffer to which the variable value is copied
- * @data: buffer to which the variable value is copied
- * Return: status code
- */
-efi_status_t EFIAPI efi_get_variable(u16 *variable_name,
- const efi_guid_t *vendor, u32 *attributes,
- efi_uintn_t *data_size, void *data)
-{
- efi_status_t ret;
+ for (pdata = var->name; *pdata; ++pdata)
+ ;
+ ++pdata;
- EFI_ENTRY("\"%ls\" %pUl %p %p %p", variable_name, vendor, attributes,
- data_size, data);
+ efi_memcpy_runtime(data, pdata, var->length);
- ret = efi_get_variable_common(variable_name, vendor, attributes,
- data_size, data, NULL);
- return EFI_EXIT(ret);
+ return EFI_SUCCESS;
}
-static char *efi_variables_list;
-static char *efi_cur_variable;
-
-/**
- * parse_uboot_variable() - parse a u-boot variable and get uefi-related
- * information
- * @variable: whole data of u-boot variable (ie. name=value)
- * @variable_name_size: size of variable_name buffer in byte
- * @variable_name: name of uefi variable in u16, null-terminated
- * @vendor: vendor's guid
- * @attributes: attributes
- *
- * A uefi variable is encoded into a u-boot variable as described above.
- * This function parses such a u-boot variable and retrieve uefi-related
- * information into respective parameters. In return, variable_name_size
- * is the size of variable name including NULL.
- *
- * Return: EFI_SUCCESS if parsing is OK, EFI_NOT_FOUND when
- * the entire variable list has been returned,
- * otherwise non-zero status code
- */
-static efi_status_t parse_uboot_variable(char *variable,
- efi_uintn_t *variable_name_size,
- u16 *variable_name,
- const efi_guid_t *vendor,
- u32 *attributes)
+efi_status_t __efi_runtime
+efi_get_next_variable_name_int(efi_uintn_t *variable_name_size,
+ u16 *variable_name, efi_guid_t *vendor)
{
- char *guid, *name, *end, c;
- size_t name_len;
- efi_uintn_t old_variable_name_size;
- u64 time;
- u16 *p;
-
- guid = strchr(variable, '_');
- if (!guid)
- return EFI_INVALID_PARAMETER;
- guid++;
- name = strchr(guid, '_');
- if (!name)
- return EFI_INVALID_PARAMETER;
- name++;
- end = strchr(name, '=');
- if (!end)
- return EFI_INVALID_PARAMETER;
-
- name_len = end - name;
- old_variable_name_size = *variable_name_size;
- *variable_name_size = sizeof(u16) * (name_len + 1);
- if (old_variable_name_size < *variable_name_size)
- return EFI_BUFFER_TOO_SMALL;
-
- end++; /* point to value */
-
- /* variable name */
- p = variable_name;
- utf8_utf16_strncpy(&p, name, name_len);
- variable_name[name_len] = 0;
+ struct efi_var_entry *var;
+ efi_uintn_t old_size;
+ u16 *pdata;
- /* guid */
- c = *(name - 1);
- *(name - 1) = '\0'; /* guid need be null-terminated here */
- if (uuid_str_to_bin(guid, (unsigned char *)vendor,
- UUID_STR_FORMAT_GUID))
- /* The only error would be EINVAL. */
+ if (!variable_name_size || !variable_name || !vendor)
return EFI_INVALID_PARAMETER;
- *(name - 1) = c;
- /* attributes */
- parse_attr(end, attributes, &time);
+ efi_var_mem_find(vendor, variable_name, &var);
- return EFI_SUCCESS;
-}
-
-/**
- * efi_get_next_variable_name() - enumerate the current variable names
- *
- * @variable_name_size: size of variable_name buffer in byte
- * @variable_name: name of uefi variable's name in u16
- * @vendor: vendor's guid
- *
- * This function implements the GetNextVariableName service.
- *
- * See the Unified Extensible Firmware Interface (UEFI) specification for
- * details.
- *
- * Return: status code
- */
-efi_status_t EFIAPI efi_get_next_variable_name(efi_uintn_t *variable_name_size,
- u16 *variable_name,
- efi_guid_t *vendor)
-{
- char *native_name, *variable;
- ssize_t name_len, list_len;
- char regex[256];
- char * const regexlist[] = {regex};
- u32 attributes;
- int i;
- efi_status_t ret;
-
- EFI_ENTRY("%p \"%ls\" %pUl", variable_name_size, variable_name, vendor);
+ if (!var)
+ return EFI_NOT_FOUND;
- if (!variable_name_size || !variable_name || !vendor)
- return EFI_EXIT(EFI_INVALID_PARAMETER);
-
- if (variable_name[0]) {
- /* check null-terminated string */
- for (i = 0; i < *variable_name_size; i++)
- if (!variable_name[i])
- break;
- if (i >= *variable_name_size)
- return EFI_EXIT(EFI_INVALID_PARAMETER);
-
- /* search for the last-returned variable */
- ret = efi_to_native(&native_name, variable_name, vendor);
- if (ret)
- return EFI_EXIT(ret);
-
- name_len = strlen(native_name);
- for (variable = efi_variables_list; variable && *variable;) {
- if (!strncmp(variable, native_name, name_len) &&
- variable[name_len] == '=')
- break;
-
- variable = strchr(variable, '\n');
- if (variable)
- variable++;
- }
+ for (pdata = var->name; *pdata; ++pdata)
+ ;
+ ++pdata;
- free(native_name);
- if (!(variable && *variable))
- return EFI_EXIT(EFI_INVALID_PARAMETER);
+ old_size = *variable_name_size;
+ *variable_name_size = (uintptr_t)pdata - (uintptr_t)var->name;
- /* next variable */
- variable = strchr(variable, '\n');
- if (variable)
- variable++;
- if (!(variable && *variable))
- return EFI_EXIT(EFI_NOT_FOUND);
- } else {
- /*
- *new search: free a list used in the previous search
- */
- free(efi_variables_list);
- efi_variables_list = NULL;
- efi_cur_variable = NULL;
-
- snprintf(regex, 256, "efi_.*-.*-.*-.*-.*_.*");
- list_len = hexport_r(&env_htab, '\n',
- H_MATCH_REGEX | H_MATCH_KEY,
- &efi_variables_list, 0, 1, regexlist);
-
- if (list_len <= 1)
- return EFI_EXIT(EFI_NOT_FOUND);
-
- variable = efi_variables_list;
- }
+ if (old_size < *variable_name_size)
+ return EFI_BUFFER_TOO_SMALL;
- ret = parse_uboot_variable(variable, variable_name_size, variable_name,
- vendor, &attributes);
+ efi_memcpy_runtime(variable_name, var->name, *variable_name_size);
+ efi_memcpy_runtime(vendor, &var->guid, sizeof(efi_guid_t));
- return EFI_EXIT(ret);
+ return EFI_SUCCESS;
}
-static efi_status_t efi_set_variable_common(u16 *variable_name,
- const efi_guid_t *vendor,
- u32 attributes,
- efi_uintn_t data_size,
- const void *data,
- bool ro_check)
+efi_status_t efi_set_variable_int(u16 *variable_name, const efi_guid_t *vendor,
+ u32 attributes, efi_uintn_t data_size,
+ const void *data, bool ro_check)
{
- char *native_name = NULL, *old_data = NULL, *val = NULL, *s;
- efi_uintn_t old_size;
+ struct efi_var_entry *var;
+ efi_uintn_t ret;
bool append, delete;
u64 time = 0;
- u32 attr;
- efi_status_t ret = EFI_SUCCESS;
if (!variable_name || !*variable_name || !vendor ||
((attributes & EFI_VARIABLE_RUNTIME_ACCESS) &&
- !(attributes & EFI_VARIABLE_BOOTSERVICE_ACCESS))) {
- ret = EFI_INVALID_PARAMETER;
- goto err;
- }
-
- ret = efi_to_native(&native_name, variable_name, vendor);
- if (ret)
- goto err;
+ !(attributes & EFI_VARIABLE_BOOTSERVICE_ACCESS)))
+ return EFI_INVALID_PARAMETER;
/* check if a variable exists */
- old_size = 0;
- attr = 0;
- ret = efi_get_variable_common(variable_name, vendor, &attr,
- &old_size, NULL, &time);
+ var = efi_var_mem_find(vendor, variable_name, NULL);
append = !!(attributes & EFI_VARIABLE_APPEND_WRITE);
attributes &= ~(u32)EFI_VARIABLE_APPEND_WRITE;
delete = !append && (!data_size || !attributes);
/* check attributes */
- if (old_size) {
- if (ro_check && (attr & READ_ONLY)) {
- ret = EFI_WRITE_PROTECTED;
- goto err;
- }
+ if (var) {
+ if (ro_check && (var->attr & EFI_VARIABLE_READ_ONLY))
+ return EFI_WRITE_PROTECTED;
/* attributes won't be changed */
if (!delete &&
- ((ro_check && attr != attributes) ||
- (!ro_check && ((attr & ~(u32)READ_ONLY)
- != (attributes & ~(u32)READ_ONLY))))) {
- ret = EFI_INVALID_PARAMETER;
- goto err;
+ ((ro_check && var->attr != attributes) ||
+ (!ro_check && ((var->attr & ~(u32)EFI_VARIABLE_READ_ONLY)
+ != (attributes & ~(u32)EFI_VARIABLE_READ_ONLY))))) {
+ return EFI_INVALID_PARAMETER;
}
+ time = var->time;
} else {
- if (delete || append) {
+ if (delete || append)
/*
* Trying to delete or to update a non-existent
* variable.
*/
- ret = EFI_NOT_FOUND;
- goto err;
- }
+ return EFI_NOT_FOUND;
}
if (((!u16_strcmp(variable_name, L"PK") ||
@@ -950,27 +549,26 @@ static efi_status_t efi_set_variable_common(u16 *variable_name,
/* authentication is mandatory */
if (!(attributes &
EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS)) {
- EFI_PRINT("%ls: AUTHENTICATED_WRITE_ACCESS required\n",
+ EFI_PRINT("%ls: TIME_BASED_AUTHENTICATED_WRITE_ACCESS required\n",
variable_name);
- ret = EFI_INVALID_PARAMETER;
- goto err;
+ return EFI_INVALID_PARAMETER;
}
}
/* authenticate a variable */
if (IS_ENABLED(CONFIG_EFI_SECURE_BOOT)) {
- if (attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) {
- ret = EFI_INVALID_PARAMETER;
- goto err;
- }
+ if (attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS)
+ return EFI_INVALID_PARAMETER;
if (attributes &
EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) {
+ u32 env_attr;
+
ret = efi_variable_authenticate(variable_name, vendor,
&data_size, &data,
- attributes, &attr,
+ attributes, &env_attr,
&time);
if (ret != EFI_SUCCESS)
- goto err;
+ return ret;
/* last chance to check for delete */
if (!data_size)
@@ -981,168 +579,61 @@ static efi_status_t efi_set_variable_common(u16 *variable_name,
(EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS |
EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS)) {
EFI_PRINT("Secure boot is not configured\n");
- ret = EFI_INVALID_PARAMETER;
- goto err;
+ return EFI_INVALID_PARAMETER;
}
}
- /* delete a variable */
if (delete) {
- /* !old_size case has been handled before */
- val = NULL;
+ /* EFI_NOT_FOUND has been handled before */
ret = EFI_SUCCESS;
- goto out;
- }
-
- if (append) {
- old_data = malloc(old_size);
- if (!old_data) {
- ret = EFI_OUT_OF_RESOURCES;
- goto err;
- }
- ret = efi_get_variable_common(variable_name, vendor,
- &attr, &old_size, old_data, NULL);
- if (ret != EFI_SUCCESS)
- goto err;
+ } else if (append) {
+ u16 *old_data = var->name;
+
+ for (; *old_data; ++old_data)
+ ;
+ ++old_data;
+ ret = efi_var_mem_ins(variable_name, vendor, attributes,
+ var->length, old_data, data_size, data,
+ time);
} else {
- old_size = 0;
- }
-
- val = malloc(2 * old_size + 2 * data_size
- + strlen("{ro,run,boot,nv,time=0123456701234567}(blob)")
- + 1);
- if (!val) {
- ret = EFI_OUT_OF_RESOURCES;
- goto err;
+ ret = efi_var_mem_ins(variable_name, vendor, attributes,
+ data_size, data, 0, NULL, time);
}
+ efi_var_mem_del(var);
- s = val;
-
- /*
- * store attributes
- */
- attributes &= (READ_ONLY |
- EFI_VARIABLE_NON_VOLATILE |
- EFI_VARIABLE_BOOTSERVICE_ACCESS |
- EFI_VARIABLE_RUNTIME_ACCESS |
- EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS);
- s += sprintf(s, "{");
- while (attributes) {
- attr = 1 << (ffs(attributes) - 1);
-
- if (attr == READ_ONLY) {
- s += sprintf(s, "ro");
- } else if (attr == EFI_VARIABLE_NON_VOLATILE) {
- s += sprintf(s, "nv");
- } else if (attr == EFI_VARIABLE_BOOTSERVICE_ACCESS) {
- s += sprintf(s, "boot");
- } else if (attr == EFI_VARIABLE_RUNTIME_ACCESS) {
- s += sprintf(s, "run");
- } else if (attr ==
- EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) {
- s += sprintf(s, "time=");
- s = bin2hex(s, (u8 *)&time, sizeof(time));
- }
-
- attributes &= ~attr;
- if (attributes)
- s += sprintf(s, ",");
- }
- s += sprintf(s, "}");
- s += sprintf(s, "(blob)");
-
- /* store payload: */
- if (append)
- s = bin2hex(s, old_data, old_size);
- s = bin2hex(s, data, data_size);
- *s = '\0';
-
- EFI_PRINT("setting: %s=%s\n", native_name, val);
-
-out:
- if (env_set(native_name, val)) {
- ret = EFI_DEVICE_ERROR;
- } else {
- bool vendor_keys_modified = false;
-
- if ((u16_strcmp(variable_name, L"PK") == 0 &&
- guidcmp(vendor, &efi_global_variable_guid) == 0)) {
- ret = efi_transfer_secure_state(
- (delete ? EFI_MODE_SETUP :
- EFI_MODE_USER));
- if (ret != EFI_SUCCESS)
- goto err;
-
- if (efi_secure_mode != EFI_MODE_SETUP)
- vendor_keys_modified = true;
- } else if ((u16_strcmp(variable_name, L"KEK") == 0 &&
- guidcmp(vendor, &efi_global_variable_guid) == 0)) {
- if (efi_secure_mode != EFI_MODE_SETUP)
- vendor_keys_modified = true;
- }
+ if (ret != EFI_SUCCESS)
+ return ret;
- /* update VendorKeys */
- if (vendor_keys_modified & efi_vendor_keys) {
- efi_vendor_keys = 0;
- ret = efi_set_variable_common(
- L"VendorKeys",
- &efi_global_variable_guid,
- EFI_VARIABLE_BOOTSERVICE_ACCESS
- | EFI_VARIABLE_RUNTIME_ACCESS
- | READ_ONLY,
- sizeof(efi_vendor_keys),
- &efi_vendor_keys,
- false);
- } else {
- ret = EFI_SUCCESS;
- }
- }
+ if (!u16_strcmp(variable_name, L"PK"))
+ ret = efi_init_secure_state();
+ else
+ ret = EFI_SUCCESS;
-err:
- free(native_name);
- free(old_data);
- free(val);
+ /* Write non-volatile EFI variables to file */
+ if (attributes & EFI_VARIABLE_NON_VOLATILE &&
+ ret == EFI_SUCCESS && efi_obj_list_initialized == EFI_SUCCESS)
+ efi_var_to_file();
- return ret;
+ return EFI_SUCCESS;
}
-/**
- * efi_set_variable() - set value of a UEFI variable
- *
- * This function implements the SetVariable runtime service.
- *
- * See the Unified Extensible Firmware Interface (UEFI) specification for
- * details.
- *
- * @variable_name: name of the variable
- * @vendor: vendor GUID
- * @attributes: attributes of the variable
- * @data_size: size of the buffer with the variable value
- * @data: buffer with the variable value
- * Return: status code
- */
-efi_status_t EFIAPI efi_set_variable(u16 *variable_name,
- const efi_guid_t *vendor, u32 attributes,
- efi_uintn_t data_size, const void *data)
+efi_status_t efi_query_variable_info_int(u32 attributes,
+ u64 *maximum_variable_storage_size,
+ u64 *remaining_variable_storage_size,
+ u64 *maximum_variable_size)
{
- EFI_ENTRY("\"%ls\" %pUl %x %zu %p", variable_name, vendor, attributes,
- data_size, data);
-
- /* READ_ONLY bit is not part of API */
- attributes &= ~(u32)READ_ONLY;
-
- return EFI_EXIT(efi_set_variable_common(variable_name, vendor,
- attributes, data_size, data,
- true));
+ *maximum_variable_storage_size = EFI_VAR_BUF_SIZE -
+ sizeof(struct efi_var_file);
+ *remaining_variable_storage_size = efi_var_mem_free();
+ *maximum_variable_size = EFI_VAR_BUF_SIZE -
+ sizeof(struct efi_var_file) -
+ sizeof(struct efi_var_entry);
+ return EFI_SUCCESS;
}
/**
- * efi_query_variable_info() - get information about EFI variables
- *
- * This function implements the QueryVariableInfo() runtime service.
- *
- * See the Unified Extensible Firmware Interface (UEFI) specification for
- * details.
+ * efi_query_variable_info_runtime() - runtime implementation of
+ * QueryVariableInfo()
*
* @attributes: bitmask to select variables to be
* queried
@@ -1154,7 +645,7 @@ efi_status_t EFIAPI efi_set_variable(u16 *variable_name,
* selected type
* Returns: status code
*/
-efi_status_t __efi_runtime EFIAPI efi_query_variable_info(
+efi_status_t __efi_runtime EFIAPI efi_query_variable_info_runtime(
u32 attributes,
u64 *maximum_variable_storage_size,
u64 *remaining_variable_storage_size,
@@ -1177,7 +668,16 @@ static efi_status_t __efi_runtime EFIAPI
efi_get_variable_runtime(u16 *variable_name, const efi_guid_t *vendor,
u32 *attributes, efi_uintn_t *data_size, void *data)
{
- return EFI_UNSUPPORTED;
+ efi_status_t ret;
+
+ ret = efi_get_variable_int(variable_name, vendor, attributes,
+ data_size, data, NULL);
+
+ /* Remove EFI_VARIABLE_READ_ONLY flag */
+ if (attributes)
+ *attributes &= EFI_VARIABLE_MASK;
+
+ return ret;
}
/**
@@ -1193,7 +693,8 @@ static efi_status_t __efi_runtime EFIAPI
efi_get_next_variable_name_runtime(efi_uintn_t *variable_name_size,
u16 *variable_name, efi_guid_t *vendor)
{
- return EFI_UNSUPPORTED;
+ return efi_get_next_variable_name_int(variable_name_size, variable_name,
+ vendor);
}
/**
@@ -1219,10 +720,13 @@ efi_set_variable_runtime(u16 *variable_name, const efi_guid_t *vendor,
*/
void efi_variables_boot_exit_notify(void)
{
+ /* Switch variable services functions to runtime version */
efi_runtime_services.get_variable = efi_get_variable_runtime;
efi_runtime_services.get_next_variable_name =
efi_get_next_variable_name_runtime;
efi_runtime_services.set_variable = efi_set_variable_runtime;
+ efi_runtime_services.query_variable_info =
+ efi_query_variable_info_runtime;
efi_update_table_header_crc32(&efi_runtime_services.hdr);
}
@@ -1235,7 +739,13 @@ efi_status_t efi_init_variables(void)
{
efi_status_t ret;
+ ret = efi_var_mem_init();
+ if (ret != EFI_SUCCESS)
+ return ret;
+
ret = efi_init_secure_state();
+ if (ret != EFI_SUCCESS)
+ return ret;
- return ret;
+ return efi_var_from_file();
}
diff --git a/lib/efi_loader/efi_variable_tee.c b/lib/efi_loader/efi_variable_tee.c
index cacc76e23db..ff90aa8e81c 100644
--- a/lib/efi_loader/efi_variable_tee.c
+++ b/lib/efi_loader/efi_variable_tee.c
@@ -10,6 +10,7 @@
#include <efi.h>
#include <efi_api.h>
#include <efi_loader.h>
+#include <efi_variable.h>
#include <tee.h>
#include <malloc.h>
#include <mm_communication.h>
@@ -243,24 +244,9 @@ out:
return ret;
}
-/**
- * efi_get_variable() - retrieve value of a UEFI variable
- *
- * This function implements the GetVariable runtime service.
- *
- * See the Unified Extensible Firmware Interface (UEFI) specification for
- * details.
- *
- * @name: name of the variable
- * @guid: vendor GUID
- * @attr: attributes of the variable
- * @data_size: size of the buffer to which the variable value is copied
- * @data: buffer to which the variable value is copied
- * Return: status code
- */
-efi_status_t EFIAPI efi_get_variable(u16 *name, const efi_guid_t *guid,
- u32 *attr, efi_uintn_t *data_size,
- void *data)
+efi_status_t efi_get_variable_int(u16 *variable_name, const efi_guid_t *vendor,
+ u32 *attributes, efi_uintn_t *data_size,
+ void *data, u64 *timep)
{
struct smm_variable_access *var_acc;
efi_uintn_t payload_size;
@@ -269,15 +255,13 @@ efi_status_t EFIAPI efi_get_variable(u16 *name, const efi_guid_t *guid,
u8 *comm_buf = NULL;
efi_status_t ret;
- EFI_ENTRY("\"%ls\" %pUl %p %p %p", name, guid, attr, data_size, data);
-
- if (!name || !guid || !data_size) {
+ if (!variable_name || !vendor || !data_size) {
ret = EFI_INVALID_PARAMETER;
goto out;
}
/* Check payload size */
- name_size = u16_strsize(name);
+ name_size = u16_strsize(variable_name);
if (name_size > max_payload_size - MM_VARIABLE_ACCESS_HEADER_SIZE) {
ret = EFI_INVALID_PARAMETER;
goto out;
@@ -300,11 +284,11 @@ efi_status_t EFIAPI efi_get_variable(u16 *name, const efi_guid_t *guid,
goto out;
/* Fill in contents */
- guidcpy(&var_acc->guid, guid);
+ guidcpy(&var_acc->guid, vendor);
var_acc->data_size = tmp_dsize;
var_acc->name_size = name_size;
- var_acc->attr = attr ? *attr : 0;
- memcpy(var_acc->name, name, name_size);
+ var_acc->attr = attributes ? *attributes : 0;
+ memcpy(var_acc->name, variable_name, name_size);
/* Communicate */
ret = mm_communicate(comm_buf, payload_size);
@@ -315,8 +299,8 @@ efi_status_t EFIAPI efi_get_variable(u16 *name, const efi_guid_t *guid,
if (ret != EFI_SUCCESS)
goto out;
- if (attr)
- *attr = var_acc->attr;
+ if (attributes)
+ *attributes = var_acc->attr;
if (data)
memcpy(data, (u8 *)var_acc->name + var_acc->name_size,
var_acc->data_size);
@@ -325,38 +309,21 @@ efi_status_t EFIAPI efi_get_variable(u16 *name, const efi_guid_t *guid,
out:
free(comm_buf);
- return EFI_EXIT(ret);
+ return ret;
}
-/**
- * efi_get_next_variable_name() - enumerate the current variable names
- *
- * @variable_name_size: size of variable_name buffer in bytes
- * @variable_name: name of uefi variable's name in u16
- * @guid: vendor's guid
- *
- * This function implements the GetNextVariableName service.
- *
- * See the Unified Extensible Firmware Interface (UEFI) specification for
- * details.
- *
- * Return: status code
- */
-efi_status_t EFIAPI efi_get_next_variable_name(efi_uintn_t *variable_name_size,
- u16 *variable_name,
- efi_guid_t *guid)
+efi_status_t efi_get_next_variable_name_int(efi_uintn_t *variable_name_size,
+ u16 *variable_name,
+ efi_guid_t *guid)
{
struct smm_variable_getnext *var_getnext;
efi_uintn_t payload_size;
efi_uintn_t out_name_size;
efi_uintn_t in_name_size;
efi_uintn_t tmp_dsize;
- efi_uintn_t name_size;
u8 *comm_buf = NULL;
efi_status_t ret;
- EFI_ENTRY("%p \"%ls\" %pUl", variable_name_size, variable_name, guid);
-
if (!variable_name_size || !variable_name || !guid) {
ret = EFI_INVALID_PARAMETER;
goto out;
@@ -370,19 +337,18 @@ efi_status_t EFIAPI efi_get_next_variable_name(efi_uintn_t *variable_name_size,
goto out;
}
- name_size = u16_strsize(variable_name);
- if (name_size > max_payload_size - MM_VARIABLE_GET_NEXT_HEADER_SIZE) {
+ if (in_name_size > max_payload_size - MM_VARIABLE_GET_NEXT_HEADER_SIZE) {
ret = EFI_INVALID_PARAMETER;
goto out;
}
/* Trim output buffer size */
tmp_dsize = *variable_name_size;
- if (name_size + tmp_dsize >
+ if (in_name_size + tmp_dsize >
max_payload_size - MM_VARIABLE_GET_NEXT_HEADER_SIZE) {
tmp_dsize = max_payload_size -
MM_VARIABLE_GET_NEXT_HEADER_SIZE -
- name_size;
+ in_name_size;
}
payload_size = MM_VARIABLE_GET_NEXT_HEADER_SIZE + out_name_size;
@@ -414,27 +380,12 @@ efi_status_t EFIAPI efi_get_next_variable_name(efi_uintn_t *variable_name_size,
out:
free(comm_buf);
- return EFI_EXIT(ret);
+ return ret;
}
-/**
- * efi_set_variable() - set value of a UEFI variable
- *
- * This function implements the SetVariable runtime service.
- *
- * See the Unified Extensible Firmware Interface (UEFI) specification for
- * details.
- *
- * @name: name of the variable
- * @guid: vendor GUID
- * @attr: attributes of the variable
- * @data_size: size of the buffer with the variable value
- * @data: buffer with the variable value
- * Return: status code
- */
-efi_status_t EFIAPI efi_set_variable(u16 *name, const efi_guid_t *guid,
- u32 attr, efi_uintn_t data_size,
- const void *data)
+efi_status_t efi_set_variable_int(u16 *variable_name, const efi_guid_t *vendor,
+ u32 attributes, efi_uintn_t data_size,
+ const void *data, bool ro_check)
{
struct smm_variable_access *var_acc;
efi_uintn_t payload_size;
@@ -442,9 +393,7 @@ efi_status_t EFIAPI efi_set_variable(u16 *name, const efi_guid_t *guid,
u8 *comm_buf = NULL;
efi_status_t ret;
- EFI_ENTRY("\"%ls\" %pUl %x %zu %p", name, guid, attr, data_size, data);
-
- if (!name || name[0] == 0 || !guid) {
+ if (!variable_name || variable_name[0] == 0 || !vendor) {
ret = EFI_INVALID_PARAMETER;
goto out;
}
@@ -454,7 +403,7 @@ efi_status_t EFIAPI efi_set_variable(u16 *name, const efi_guid_t *guid,
}
/* Check payload size */
- name_size = u16_strsize(name);
+ name_size = u16_strsize(variable_name);
payload_size = MM_VARIABLE_ACCESS_HEADER_SIZE + name_size + data_size;
if (payload_size > max_payload_size) {
ret = EFI_INVALID_PARAMETER;
@@ -468,11 +417,11 @@ efi_status_t EFIAPI efi_set_variable(u16 *name, const efi_guid_t *guid,
goto out;
/* Fill in contents */
- guidcpy(&var_acc->guid, guid);
+ guidcpy(&var_acc->guid, vendor);
var_acc->data_size = data_size;
var_acc->name_size = name_size;
- var_acc->attr = attr;
- memcpy(var_acc->name, name, name_size);
+ var_acc->attr = attributes;
+ memcpy(var_acc->name, variable_name, name_size);
memcpy((u8 *)var_acc->name + name_size, data, data_size);
/* Communicate */
@@ -480,40 +429,19 @@ efi_status_t EFIAPI efi_set_variable(u16 *name, const efi_guid_t *guid,
out:
free(comm_buf);
- return EFI_EXIT(ret);
+ return ret;
}
-/**
- * efi_query_variable_info() - get information about EFI variables
- *
- * This function implements the QueryVariableInfo() runtime service.
- *
- * See the Unified Extensible Firmware Interface (UEFI) specification for
- * details.
- *
- * @attributes: bitmask to select variables to be
- * queried
- * @maximum_variable_storage_size: maximum size of storage area for the
- * selected variable types
- * @remaining_variable_storage_size: remaining size of storage are for the
- * selected variable types
- * @maximum_variable_size: maximum size of a variable of the
- * selected type
- * Returns: status code
- */
-efi_status_t EFIAPI __efi_runtime
-efi_query_variable_info(u32 attributes, u64 *max_variable_storage_size,
- u64 *remain_variable_storage_size,
- u64 *max_variable_size)
+efi_status_t efi_query_variable_info_int(u32 attributes,
+ u64 *max_variable_storage_size,
+ u64 *remain_variable_storage_size,
+ u64 *max_variable_size)
{
struct smm_variable_query_info *mm_query_info;
efi_uintn_t payload_size;
efi_status_t ret;
u8 *comm_buf;
- EFI_ENTRY("%x %p %p %p", attributes, max_variable_storage_size,
- remain_variable_storage_size, max_variable_size);
-
payload_size = sizeof(*mm_query_info);
comm_buf = setup_mm_hdr((void **)&mm_query_info, payload_size,
SMM_VARIABLE_FUNCTION_QUERY_VARIABLE_INFO,
@@ -532,7 +460,7 @@ efi_query_variable_info(u32 attributes, u64 *max_variable_storage_size,
out:
free(comm_buf);
- return EFI_EXIT(ret);
+ return ret;
}
/**
diff --git a/lib/efi_selftest/efi_selftest_variables_runtime.c b/lib/efi_selftest/efi_selftest_variables_runtime.c
index b3b40ad2cfc..3226069c0b2 100644
--- a/lib/efi_selftest/efi_selftest_variables_runtime.c
+++ b/lib/efi_selftest/efi_selftest_variables_runtime.c
@@ -16,9 +16,7 @@
static struct efi_boot_services *boottime;
static struct efi_runtime_services *runtime;
-static const efi_guid_t guid_vendor0 =
- EFI_GUID(0x67029eb5, 0x0af2, 0xf6b1,
- 0xda, 0x53, 0xfc, 0xb5, 0x66, 0xdd, 0x1c, 0xe6);
+static const efi_guid_t guid_vendor0 = EFI_GLOBAL_VARIABLE_GUID;
/*
* Setup unit test.
@@ -68,17 +66,18 @@ static int execute(void)
efi_st_error("SetVariable failed\n");
return EFI_ST_FAILURE;
}
- len = 3;
- ret = runtime->get_variable(L"efi_st_var0", &guid_vendor0,
+ len = EFI_ST_MAX_DATA_SIZE;
+ ret = runtime->get_variable(L"PlatformLangCodes", &guid_vendor0,
&attr, &len, data);
- if (ret != EFI_UNSUPPORTED) {
+ if (ret != EFI_SUCCESS) {
efi_st_error("GetVariable failed\n");
return EFI_ST_FAILURE;
}
memset(&guid, 0, 16);
*varname = 0;
+ len = 2 * EFI_ST_MAX_VARNAME_SIZE;
ret = runtime->get_next_variable_name(&len, varname, &guid);
- if (ret != EFI_UNSUPPORTED) {
+ if (ret != EFI_SUCCESS) {
efi_st_error("GetNextVariableName failed\n");
return EFI_ST_FAILURE;
}
diff --git a/lib/rsa/rsa-verify.c b/lib/rsa/rsa-verify.c
index 6c4bbc46250..2057f6819db 100644
--- a/lib/rsa/rsa-verify.c
+++ b/lib/rsa/rsa-verify.c
@@ -387,8 +387,8 @@ static int rsa_verify_key(struct image_sign_info *info,
*
* Return 0 if verified, -ve on error
*/
-static int rsa_verify_with_pkey(struct image_sign_info *info,
- const void *hash, uint8_t *sig, uint sig_len)
+int rsa_verify_with_pkey(struct image_sign_info *info,
+ const void *hash, uint8_t *sig, uint sig_len)
{
struct key_prop *prop;
int ret;
@@ -408,8 +408,8 @@ static int rsa_verify_with_pkey(struct image_sign_info *info,
return ret;
}
#else
-static int rsa_verify_with_pkey(struct image_sign_info *info,
- const void *hash, uint8_t *sig, uint sig_len)
+int rsa_verify_with_pkey(struct image_sign_info *info,
+ const void *hash, uint8_t *sig, uint sig_len)
{
return -EACCES;
}
diff --git a/scripts/config_whitelist.txt b/scripts/config_whitelist.txt
index ca40b9beb0c..e3bebe94c4c 100644
--- a/scripts/config_whitelist.txt
+++ b/scripts/config_whitelist.txt
@@ -312,7 +312,6 @@ CONFIG_DFU_ENV_SETTINGS
CONFIG_DHCP_MIN_EXT_LEN
CONFIG_DIALOG_POWER
CONFIG_DIMM_SLOTS_PER_CTLR
-CONFIG_DIRECT_NOR_BOOT
CONFIG_DISCONTIGMEM
CONFIG_DISCOVER_PHY
CONFIG_DISPLAY_AER_xxxx
@@ -4150,7 +4149,6 @@ CONFIG_USB_XHCI_EXYNOS
CONFIG_USB_XHCI_OMAP
CONFIG_USER_LOWLEVEL_INIT
CONFIG_USE_INTERRUPT
-CONFIG_USE_NOR
CONFIG_USE_ONENAND_BOARD_INIT
CONFIG_USE_SPIFLASH
CONFIG_UTBIPAR_INIT_TBIPA
diff --git a/test/py/tests/test_efi_secboot/conftest.py b/test/py/tests/test_efi_secboot/conftest.py
index ac5a780fdb7..c6709700a87 100644
--- a/test/py/tests/test_efi_secboot/conftest.py
+++ b/test/py/tests/test_efi_secboot/conftest.py
@@ -4,29 +4,32 @@
import os
import os.path
-import pytest
-import re
from subprocess import call, check_call, check_output, CalledProcessError
+import pytest
from defs import *
# from test/py/conftest.py
+
+
def tool_is_in_path(tool):
for path in os.environ["PATH"].split(os.pathsep):
- fn = os.path.join(path, tool)
- if os.path.isfile(fn) and os.access(fn, os.X_OK):
+ full_path = os.path.join(path, tool)
+ if os.path.isfile(full_path) and os.access(full_path, os.X_OK):
return True
return False
#
# Fixture for UEFI secure boot test
#
+
+
@pytest.fixture(scope='session')
def efi_boot_env(request, u_boot_config):
"""Set up a file system to be used in UEFI secure boot test.
Args:
request: Pytest request object.
- u_boot_config: U-boot configuration.
+ u_boot_config: U-boot configuration.
Return:
A path to disk image to be used for testing
@@ -35,34 +38,15 @@ def efi_boot_env(request, u_boot_config):
image_path = u_boot_config.persistent_data_dir
image_path = image_path + '/' + EFI_SECBOOT_IMAGE_NAME
- image_size = EFI_SECBOOT_IMAGE_SIZE
- part_size = EFI_SECBOOT_PART_SIZE
- fs_type = EFI_SECBOOT_FS_TYPE
if HELLO_PATH == '':
HELLO_PATH = u_boot_config.build_dir + '/lib/efi_loader/helloworld.efi'
try:
- mnt_point = u_boot_config.persistent_data_dir + '/mnt_efisecure'
+ mnt_point = u_boot_config.build_dir + '/mnt_efisecure'
+ check_call('rm -rf {}'.format(mnt_point), shell=True)
check_call('mkdir -p {}'.format(mnt_point), shell=True)
- # create a disk/partition
- check_call('dd if=/dev/zero of=%s bs=1MiB count=%d'
- % (image_path, image_size), shell=True)
- check_call('sgdisk %s -n 1:0:+%dMiB'
- % (image_path, part_size), shell=True)
- # create a file system
- check_call('dd if=/dev/zero of=%s.tmp bs=1MiB count=%d'
- % (image_path, part_size), shell=True)
- check_call('mkfs -t %s %s.tmp' % (fs_type, image_path), shell=True)
- check_call('dd if=%s.tmp of=%s bs=1MiB seek=1 count=%d conv=notrunc'
- % (image_path, image_path, 1), shell=True)
- check_call('rm %s.tmp' % image_path, shell=True)
- loop_dev = check_output('sudo losetup -o 1MiB --sizelimit %dMiB --show -f %s | tr -d "\n"'
- % (part_size, image_path), shell=True).decode()
- check_output('sudo mount -t %s -o umask=000 %s %s'
- % (fs_type, loop_dev, mnt_point), shell=True)
-
# suffix
# *.key: RSA private key in PEM
# *.crt: X509 certificate (self-signed) in PEM
@@ -73,59 +57,80 @@ def efi_boot_env(request, u_boot_config):
# *.efi.signed: signed UEFI image
# Create signature database
- ## PK
+ # PK
check_call('cd %s; openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=TEST_PK/ -keyout PK.key -out PK.crt -nodes -days 365'
- % mnt_point, shell=True)
+ % mnt_point, shell=True)
check_call('cd %s; %scert-to-efi-sig-list -g %s PK.crt PK.esl; %ssign-efi-sig-list -t "2020-04-01" -c PK.crt -k PK.key PK PK.esl PK.auth'
- % (mnt_point, EFITOOLS_PATH, GUID, EFITOOLS_PATH),
- shell=True)
- ## PK_null for deletion
+ % (mnt_point, EFITOOLS_PATH, GUID, EFITOOLS_PATH),
+ shell=True)
+ # PK_null for deletion
check_call('cd %s; touch PK_null.esl; %ssign-efi-sig-list -t "2020-04-02" -c PK.crt -k PK.key PK PK_null.esl PK_null.auth'
- % (mnt_point, EFITOOLS_PATH), shell=True)
- ## KEK
+ % (mnt_point, EFITOOLS_PATH), shell=True)
+ # KEK
check_call('cd %s; openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=TEST_KEK/ -keyout KEK.key -out KEK.crt -nodes -days 365'
- % mnt_point, shell=True)
+ % mnt_point, shell=True)
check_call('cd %s; %scert-to-efi-sig-list -g %s KEK.crt KEK.esl; %ssign-efi-sig-list -t "2020-04-03" -c PK.crt -k PK.key KEK KEK.esl KEK.auth'
- % (mnt_point, EFITOOLS_PATH, GUID, EFITOOLS_PATH),
- shell=True)
- ## db
+ % (mnt_point, EFITOOLS_PATH, GUID, EFITOOLS_PATH),
+ shell=True)
+ # db
check_call('cd %s; openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=TEST_db/ -keyout db.key -out db.crt -nodes -days 365'
- % mnt_point, shell=True)
+ % mnt_point, shell=True)
check_call('cd %s; %scert-to-efi-sig-list -g %s db.crt db.esl; %ssign-efi-sig-list -t "2020-04-04" -c KEK.crt -k KEK.key db db.esl db.auth'
- % (mnt_point, EFITOOLS_PATH, GUID, EFITOOLS_PATH),
- shell=True)
- ## db1
+ % (mnt_point, EFITOOLS_PATH, GUID, EFITOOLS_PATH),
+ shell=True)
+ # db1
check_call('cd %s; openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=TEST_db1/ -keyout db1.key -out db1.crt -nodes -days 365'
- % mnt_point, shell=True)
+ % mnt_point, shell=True)
check_call('cd %s; %scert-to-efi-sig-list -g %s db1.crt db1.esl; %ssign-efi-sig-list -t "2020-04-05" -c KEK.crt -k KEK.key db db1.esl db1.auth'
- % (mnt_point, EFITOOLS_PATH, GUID, EFITOOLS_PATH),
- shell=True)
- ## db1-update
+ % (mnt_point, EFITOOLS_PATH, GUID, EFITOOLS_PATH),
+ shell=True)
+ # db1-update
check_call('cd %s; %ssign-efi-sig-list -t "2020-04-06" -a -c KEK.crt -k KEK.key db db1.esl db1-update.auth'
- % (mnt_point, EFITOOLS_PATH), shell=True)
- ## dbx
+ % (mnt_point, EFITOOLS_PATH), shell=True)
+ ## dbx (TEST_dbx certificate)
check_call('cd %s; openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=TEST_dbx/ -keyout dbx.key -out dbx.crt -nodes -days 365'
- % mnt_point, shell=True)
+ % mnt_point, shell=True)
check_call('cd %s; %scert-to-efi-sig-list -g %s dbx.crt dbx.esl; %ssign-efi-sig-list -t "2020-04-05" -c KEK.crt -k KEK.key dbx dbx.esl dbx.auth'
- % (mnt_point, EFITOOLS_PATH, GUID, EFITOOLS_PATH),
- shell=True)
+ % (mnt_point, EFITOOLS_PATH, GUID, EFITOOLS_PATH),
+ shell=True)
+ ## dbx_hash (digest of TEST_db certificate)
+ check_call('cd %s; %scert-to-efi-hash-list -g %s -t 0 -s 256 db.crt dbx_hash.crl; %ssign-efi-sig-list -t "2020-04-05" -c KEK.crt -k KEK.key dbx dbx_hash.crl dbx_hash.auth'
+ % (mnt_point, EFITOOLS_PATH, GUID, EFITOOLS_PATH),
+ shell=True)
+ ## dbx_hash1 (digest of TEST_db1 certificate)
+ check_call('cd %s; %scert-to-efi-hash-list -g %s -t 0 -s 256 db1.crt dbx_hash1.crl; %ssign-efi-sig-list -t "2020-04-05" -c KEK.crt -k KEK.key dbx dbx_hash1.crl dbx_hash1.auth'
+ % (mnt_point, EFITOOLS_PATH, GUID, EFITOOLS_PATH),
+ shell=True)
+ ## dbx_db (with TEST_db certificate)
+ check_call('cd %s; %ssign-efi-sig-list -t "2020-04-05" -c KEK.crt -k KEK.key dbx db.esl dbx_db.auth'
+ % (mnt_point, EFITOOLS_PATH),
+ shell=True)
# Copy image
check_call('cp %s %s' % (HELLO_PATH, mnt_point), shell=True)
- ## Sign image
+ # Sign image
check_call('cd %s; sbsign --key db.key --cert db.crt helloworld.efi'
- % mnt_point, shell=True)
+ % mnt_point, shell=True)
+ ## Sign already-signed image with another key
+ check_call('cd %s; sbsign --key db1.key --cert db1.crt --output helloworld.efi.signed_2sigs helloworld.efi.signed'
+ % mnt_point, shell=True)
## Digest image
check_call('cd %s; %shash-to-efi-sig-list helloworld.efi db_hello.hash; %ssign-efi-sig-list -t "2020-04-07" -c KEK.crt -k KEK.key db db_hello.hash db_hello.auth'
- % (mnt_point, EFITOOLS_PATH, EFITOOLS_PATH),
- shell=True)
+ % (mnt_point, EFITOOLS_PATH, EFITOOLS_PATH),
+ shell=True)
+ check_call('cd %s; %shash-to-efi-sig-list helloworld.efi.signed db_hello_signed.hash; %ssign-efi-sig-list -t "2020-04-03" -c KEK.crt -k KEK.key db db_hello_signed.hash db_hello_signed.auth'
+ % (mnt_point, EFITOOLS_PATH, EFITOOLS_PATH),
+ shell=True)
+ check_call('cd %s; %ssign-efi-sig-list -t "2020-04-07" -c KEK.crt -k KEK.key dbx db_hello_signed.hash dbx_hello_signed.auth'
+ % (mnt_point, EFITOOLS_PATH),
+ shell=True)
- check_call('sudo umount %s' % loop_dev, shell=True)
- check_call('sudo losetup -d %s' % loop_dev, shell=True)
+ check_call('virt-make-fs --partition=gpt --size=+1M --type=vfat {} {}'.format(mnt_point, image_path), shell=True)
+ check_call('rm -rf {}'.format(mnt_point), shell=True)
- except CalledProcessError as e:
- pytest.skip('Setup failed: %s' % e.cmd)
+ except CalledProcessError as exception:
+ pytest.skip('Setup failed: %s' % exception.cmd)
return
else:
yield image_path
diff --git a/test/py/tests/test_efi_secboot/defs.py b/test/py/tests/test_efi_secboot/defs.py
index d6222809c54..ba6b9f391e6 100644
--- a/test/py/tests/test_efi_secboot/defs.py
+++ b/test/py/tests/test_efi_secboot/defs.py
@@ -1,21 +1,14 @@
# SPDX-License-Identifier: GPL-2.0+
# Disk image name
-EFI_SECBOOT_IMAGE_NAME='test_efi_secboot.img'
-
-# Size in MiB
-EFI_SECBOOT_IMAGE_SIZE=16
-EFI_SECBOOT_PART_SIZE=8
-
-# Partition file system type
-EFI_SECBOOT_FS_TYPE='vfat'
+EFI_SECBOOT_IMAGE_NAME = 'test_efi_secboot.img'
# Owner guid
-GUID='11111111-2222-3333-4444-123456789abc'
+GUID = '11111111-2222-3333-4444-123456789abc'
# v1.5.1 or earlier of efitools has a bug in sha256 calculation, and
# you need build a newer version on your own.
-EFITOOLS_PATH=''
+EFITOOLS_PATH = ''
# Hello World application for sandbox
-HELLO_PATH=''
+HELLO_PATH = ''
diff --git a/test/py/tests/test_efi_secboot/test_authvar.py b/test/py/tests/test_efi_secboot/test_authvar.py
index 148aa3123e4..d0c6b9035b1 100644
--- a/test/py/tests/test_efi_secboot/test_authvar.py
+++ b/test/py/tests/test_efi_secboot/test_authvar.py
@@ -9,7 +9,7 @@ This test verifies variable authentication
"""
import pytest
-from defs import *
+
@pytest.mark.boardspec('sandbox')
@pytest.mark.buildconfigspec('efi_secure_boot')
@@ -28,18 +28,18 @@ class TestEfiAuthVar(object):
output = u_boot_console.run_command_list([
'host bind 0 %s' % disk_img,
'printenv -e SecureBoot'])
- assert('00000000: 00' in ''.join(output))
+ assert '00000000: 00' in ''.join(output)
output = u_boot_console.run_command(
'printenv -e SetupMode')
- assert('00000000: 01' in output)
+ assert '00000000: 01' in output
with u_boot_console.log.section('Test Case 1b'):
# Test Case 1b, PK without AUTHENTICATED_WRITE_ACCESS
output = u_boot_console.run_command_list([
'fatload host 0:1 4000000 PK.auth',
'setenv -e -nv -bs -rt -i 4000000,$filesize PK'])
- assert('Failed to set EFI variable' in ''.join(output))
+ assert 'Failed to set EFI variable' in ''.join(output)
with u_boot_console.log.section('Test Case 1c'):
# Test Case 1c, install PK
@@ -47,79 +47,79 @@ class TestEfiAuthVar(object):
'fatload host 0:1 4000000 PK.auth',
'setenv -e -nv -bs -rt -at -i 4000000,$filesize PK',
'printenv -e -n PK'])
- assert('PK:' in ''.join(output))
+ assert 'PK:' in ''.join(output)
output = u_boot_console.run_command(
'printenv -e SecureBoot')
- assert('00000000: 01' in output)
+ assert '00000000: 01' in output
output = u_boot_console.run_command(
'printenv -e SetupMode')
- assert('00000000: 00' in output)
+ assert '00000000: 00' in output
with u_boot_console.log.section('Test Case 1d'):
# Test Case 1d, db/dbx without KEK
output = u_boot_console.run_command_list([
'fatload host 0:1 4000000 db.auth',
'setenv -e -nv -bs -rt -at -i 4000000,$filesize db'])
- assert('Failed to set EFI variable' in ''.join(output))
+ assert 'Failed to set EFI variable' in ''.join(output)
output = u_boot_console.run_command_list([
'fatload host 0:1 4000000 db.auth',
'setenv -e -nv -bs -rt -at -i 4000000,$filesize dbx'])
- assert('Failed to set EFI variable' in ''.join(output))
+ assert 'Failed to set EFI variable' in ''.join(output)
with u_boot_console.log.section('Test Case 1e'):
# Test Case 1e, install KEK
output = u_boot_console.run_command_list([
'fatload host 0:1 4000000 KEK.auth',
'setenv -e -nv -bs -rt -i 4000000,$filesize KEK'])
- assert('Failed to set EFI variable' in ''.join(output))
+ assert 'Failed to set EFI variable' in ''.join(output)
output = u_boot_console.run_command_list([
'fatload host 0:1 4000000 KEK.auth',
'setenv -e -nv -bs -rt -at -i 4000000,$filesize KEK',
'printenv -e -n KEK'])
- assert('KEK:' in ''.join(output))
+ assert 'KEK:' in ''.join(output)
output = u_boot_console.run_command(
'printenv -e SecureBoot')
- assert('00000000: 01' in output)
+ assert '00000000: 01' in output
with u_boot_console.log.section('Test Case 1f'):
# Test Case 1f, install db
output = u_boot_console.run_command_list([
'fatload host 0:1 4000000 db.auth',
'setenv -e -nv -bs -rt -i 4000000,$filesize db'])
- assert('Failed to set EFI variable' in ''.join(output))
+ assert 'Failed to set EFI variable' in ''.join(output)
output = u_boot_console.run_command_list([
'fatload host 0:1 4000000 db.auth',
'setenv -e -nv -bs -rt -at -i 4000000,$filesize db',
'printenv -e -n -guid d719b2cb-3d3a-4596-a3bc-dad00e67656f db'])
- assert(not 'Failed to set EFI variable' in ''.join(output))
- assert('db:' in ''.join(output))
+ assert 'Failed to set EFI variable' not in ''.join(output)
+ assert 'db:' in ''.join(output)
output = u_boot_console.run_command(
'printenv -e SecureBoot')
- assert('00000000: 01' in output)
+ assert '00000000: 01' in output
with u_boot_console.log.section('Test Case 1g'):
# Test Case 1g, install dbx
output = u_boot_console.run_command_list([
'fatload host 0:1 4000000 dbx.auth',
'setenv -e -nv -bs -rt -i 4000000,$filesize dbx'])
- assert('Failed to set EFI variable' in ''.join(output))
+ assert 'Failed to set EFI variable' in ''.join(output)
output = u_boot_console.run_command_list([
'fatload host 0:1 4000000 dbx.auth',
'setenv -e -nv -bs -rt -at -i 4000000,$filesize dbx',
'printenv -e -n -guid d719b2cb-3d3a-4596-a3bc-dad00e67656f dbx'])
- assert(not 'Failed to set EFI variable' in ''.join(output))
- assert('dbx:' in ''.join(output))
+ assert 'Failed to set EFI variable' not in ''.join(output)
+ assert 'dbx:' in ''.join(output)
output = u_boot_console.run_command(
'printenv -e SecureBoot')
- assert('00000000: 01' in output)
+ assert '00000000: 01' in output
def test_efi_var_auth2(self, u_boot_console, efi_boot_env):
"""
@@ -138,20 +138,20 @@ class TestEfiAuthVar(object):
'fatload host 0:1 4000000 db.auth',
'setenv -e -nv -bs -rt -at -i 4000000,$filesize db',
'printenv -e -n -guid d719b2cb-3d3a-4596-a3bc-dad00e67656f db'])
- assert(not 'Failed to set EFI variable' in ''.join(output))
- assert('db:' in ''.join(output))
+ assert 'Failed to set EFI variable' not in ''.join(output)
+ assert 'db:' in ''.join(output)
output = u_boot_console.run_command_list([
'fatload host 0:1 4000000 db1.auth',
'setenv -e -nv -bs -rt -i 4000000,$filesize db'])
- assert('Failed to set EFI variable' in ''.join(output))
+ assert 'Failed to set EFI variable' in ''.join(output)
with u_boot_console.log.section('Test Case 2b'):
# Test Case 2b, update without correct signature
output = u_boot_console.run_command_list([
'fatload host 0:1 4000000 db.esl',
'setenv -e -nv -bs -rt -at -i 4000000,$filesize db'])
- assert('Failed to set EFI variable' in ''.join(output))
+ assert 'Failed to set EFI variable' in ''.join(output)
with u_boot_console.log.section('Test Case 2c'):
# Test Case 2c, update with correct signature
@@ -159,8 +159,8 @@ class TestEfiAuthVar(object):
'fatload host 0:1 4000000 db1.auth',
'setenv -e -nv -bs -rt -at -i 4000000,$filesize db',
'printenv -e -n -guid d719b2cb-3d3a-4596-a3bc-dad00e67656f db'])
- assert(not 'Failed to set EFI variable' in ''.join(output))
- assert('db:' in ''.join(output))
+ assert 'Failed to set EFI variable' not in ''.join(output)
+ assert 'db:' in ''.join(output)
def test_efi_var_auth3(self, u_boot_console, efi_boot_env):
"""
@@ -179,20 +179,20 @@ class TestEfiAuthVar(object):
'fatload host 0:1 4000000 db.auth',
'setenv -e -nv -bs -rt -at -i 4000000,$filesize db',
'printenv -e -n -guid d719b2cb-3d3a-4596-a3bc-dad00e67656f db'])
- assert(not 'Failed to set EFI variable' in ''.join(output))
- assert('db:' in ''.join(output))
+ assert 'Failed to set EFI variable' not in ''.join(output)
+ assert 'db:' in ''.join(output)
output = u_boot_console.run_command_list([
'fatload host 0:1 4000000 db1.auth',
'setenv -e -nv -bs -rt -a -i 4000000,$filesize db'])
- assert('Failed to set EFI variable' in ''.join(output))
+ assert 'Failed to set EFI variable' in ''.join(output)
with u_boot_console.log.section('Test Case 3b'):
# Test Case 3b, update without correct signature
output = u_boot_console.run_command_list([
'fatload host 0:1 4000000 db.esl',
'setenv -e -nv -bs -rt -at -a -i 4000000,$filesize db'])
- assert('Failed to set EFI variable' in ''.join(output))
+ assert 'Failed to set EFI variable' in ''.join(output)
with u_boot_console.log.section('Test Case 3c'):
# Test Case 3c, update with correct signature
@@ -200,8 +200,8 @@ class TestEfiAuthVar(object):
'fatload host 0:1 4000000 db1.auth',
'setenv -e -nv -bs -rt -at -a -i 4000000,$filesize db',
'printenv -e -n -guid d719b2cb-3d3a-4596-a3bc-dad00e67656f db'])
- assert(not 'Failed to set EFI variable' in ''.join(output))
- assert('db:' in ''.join(output))
+ assert 'Failed to set EFI variable' not in ''.join(output)
+ assert 'db:' in ''.join(output)
def test_efi_var_auth4(self, u_boot_console, efi_boot_env):
"""
@@ -220,22 +220,22 @@ class TestEfiAuthVar(object):
'fatload host 0:1 4000000 db.auth',
'setenv -e -nv -bs -rt -at -i 4000000,$filesize db',
'printenv -e -n -guid d719b2cb-3d3a-4596-a3bc-dad00e67656f db'])
- assert(not 'Failed to set EFI variable' in ''.join(output))
- assert('db:' in ''.join(output))
+ assert 'Failed to set EFI variable' not in ''.join(output)
+ assert 'db:' in ''.join(output)
output = u_boot_console.run_command_list([
'setenv -e -nv -bs -rt db',
'printenv -e -n -guid d719b2cb-3d3a-4596-a3bc-dad00e67656f db'])
- assert('Failed to set EFI variable' in ''.join(output))
- assert('db:' in ''.join(output))
+ assert 'Failed to set EFI variable' in ''.join(output)
+ assert 'db:' in ''.join(output)
with u_boot_console.log.section('Test Case 4b'):
# Test Case 4b, update without correct signature/data
output = u_boot_console.run_command_list([
'setenv -e -nv -bs -rt -at db',
'printenv -e -n -guid d719b2cb-3d3a-4596-a3bc-dad00e67656f db'])
- assert('Failed to set EFI variable' in ''.join(output))
- assert('db:' in ''.join(output))
+ assert 'Failed to set EFI variable' in ''.join(output)
+ assert 'db:' in ''.join(output)
def test_efi_var_auth5(self, u_boot_console, efi_boot_env):
"""
@@ -254,15 +254,15 @@ class TestEfiAuthVar(object):
'fatload host 0:1 4000000 db.auth',
'setenv -e -nv -bs -rt -at -i 4000000,$filesize db',
'printenv -e -n PK'])
- assert(not 'Failed to set EFI variable' in ''.join(output))
- assert('PK:' in ''.join(output))
+ assert 'Failed to set EFI variable' not in ''.join(output)
+ assert 'PK:' in ''.join(output)
output = u_boot_console.run_command_list([
'fatload host 0:1 4000000 PK_null.esl',
'setenv -e -nv -bs -rt -at -i 4000000,$filesize PK',
'printenv -e -n PK'])
- assert('Failed to set EFI variable' in ''.join(output))
- assert('PK:' in ''.join(output))
+ assert 'Failed to set EFI variable' in ''.join(output)
+ assert 'PK:' in ''.join(output)
with u_boot_console.log.section('Test Case 5b'):
# Test Case 5b, Uninstall PK with correct signature
@@ -270,12 +270,12 @@ class TestEfiAuthVar(object):
'fatload host 0:1 4000000 PK_null.auth',
'setenv -e -nv -bs -rt -at -i 4000000,$filesize PK',
'printenv -e -n PK'])
- assert(not 'Failed to set EFI variable' in ''.join(output))
- assert('\"PK\" not defined' in ''.join(output))
+ assert 'Failed to set EFI variable' not in ''.join(output)
+ assert '\"PK\" not defined' in ''.join(output)
output = u_boot_console.run_command(
'printenv -e SecureBoot')
- assert('00000000: 00' in output)
+ assert '00000000: 00' in output
output = u_boot_console.run_command(
'printenv -e SetupMode')
- assert('00000000: 01' in output)
+ assert '00000000: 01' in output
diff --git a/test/py/tests/test_efi_secboot/test_signed.py b/test/py/tests/test_efi_secboot/test_signed.py
index 19d78b1b64e..7531bbac6a5 100644
--- a/test/py/tests/test_efi_secboot/test_signed.py
+++ b/test/py/tests/test_efi_secboot/test_signed.py
@@ -9,7 +9,7 @@ This test verifies image authentication for signed images.
"""
import pytest
-from defs import *
+
@pytest.mark.boardspec('sandbox')
@pytest.mark.buildconfigspec('efi_secure_boot')
@@ -20,62 +20,80 @@ from defs import *
class TestEfiSignedImage(object):
def test_efi_signed_image_auth1(self, u_boot_console, efi_boot_env):
"""
- Test Case 1 - authenticated by db
+ Test Case 1 - Secure boot is not in force
"""
u_boot_console.restart_uboot()
disk_img = efi_boot_env
with u_boot_console.log.section('Test Case 1a'):
- # Test Case 1a, run signed image if no db/dbx
+ # Test Case 1a, run signed image if no PK
output = u_boot_console.run_command_list([
'host bind 0 %s' % disk_img,
'efidebug boot add 1 HELLO1 host 0:1 /helloworld.efi.signed ""',
'efidebug boot next 1',
'bootefi bootmgr'])
- assert('Hello, world!' in ''.join(output))
+ assert 'Hello, world!' in ''.join(output)
with u_boot_console.log.section('Test Case 1b'):
- # Test Case 1b, run unsigned image if no db/dbx
+ # Test Case 1b, run unsigned image if no PK
output = u_boot_console.run_command_list([
'efidebug boot add 2 HELLO2 host 0:1 /helloworld.efi ""',
'efidebug boot next 2',
'bootefi bootmgr'])
- assert('Hello, world!' in ''.join(output))
+ assert 'Hello, world!' in ''.join(output)
- with u_boot_console.log.section('Test Case 1c'):
- # Test Case 1c, not authenticated by db
+ def test_efi_signed_image_auth2(self, u_boot_console, efi_boot_env):
+ """
+ Test Case 2 - Secure boot is in force,
+ authenticated by db (TEST_db certificate in db)
+ """
+ u_boot_console.restart_uboot()
+ disk_img = efi_boot_env
+ with u_boot_console.log.section('Test Case 2a'):
+ # Test Case 2a, db is not yet installed
output = u_boot_console.run_command_list([
- 'fatload host 0:1 4000000 db.auth',
- 'setenv -e -nv -bs -rt -at -i 4000000,$filesize db',
+ 'host bind 0 %s' % disk_img,
'fatload host 0:1 4000000 KEK.auth',
'setenv -e -nv -bs -rt -at -i 4000000,$filesize KEK',
'fatload host 0:1 4000000 PK.auth',
'setenv -e -nv -bs -rt -at -i 4000000,$filesize PK'])
- assert(not 'Failed to set EFI variable' in ''.join(output))
+ assert 'Failed to set EFI variable' not in ''.join(output)
output = u_boot_console.run_command_list([
- 'efidebug boot next 2',
- 'bootefi bootmgr'])
- assert('\'HELLO2\' failed' in ''.join(output))
+ 'efidebug boot add 1 HELLO1 host 0:1 /helloworld.efi.signed ""',
+ 'efidebug boot next 1',
+ 'efidebug test bootmgr'])
+ assert('\'HELLO1\' failed' in ''.join(output))
+ assert('efi_start_image() returned: 26' in ''.join(output))
output = u_boot_console.run_command_list([
+ 'efidebug boot add 2 HELLO2 host 0:1 /helloworld.efi ""',
'efidebug boot next 2',
'efidebug test bootmgr'])
- assert('efi_start_image() returned: 26' in ''.join(output))
- assert(not 'Hello, world!' in ''.join(output))
+ assert '\'HELLO2\' failed' in ''.join(output)
+ assert 'efi_start_image() returned: 26' in ''.join(output)
- with u_boot_console.log.section('Test Case 1d'):
- # Test Case 1d, authenticated by db
+ with u_boot_console.log.section('Test Case 2b'):
+ # Test Case 2b, authenticated by db
+ output = u_boot_console.run_command_list([
+ 'fatload host 0:1 4000000 db.auth',
+ 'setenv -e -nv -bs -rt -at -i 4000000,$filesize db'])
+ assert 'Failed to set EFI variable' not in ''.join(output)
+ output = u_boot_console.run_command_list([
+ 'efidebug boot next 2',
+ 'efidebug test bootmgr'])
+ assert '\'HELLO2\' failed' in ''.join(output)
+ assert 'efi_start_image() returned: 26' in ''.join(output)
output = u_boot_console.run_command_list([
'efidebug boot next 1',
'bootefi bootmgr'])
- assert('Hello, world!' in ''.join(output))
+ assert 'Hello, world!' in ''.join(output)
- def test_efi_signed_image_auth2(self, u_boot_console, efi_boot_env):
+ def test_efi_signed_image_auth3(self, u_boot_console, efi_boot_env):
"""
- Test Case 2 - rejected by dbx
+ Test Case 3 - rejected by dbx (TEST_db certificate in dbx)
"""
u_boot_console.restart_uboot()
disk_img = efi_boot_env
- with u_boot_console.log.section('Test Case 2a'):
- # Test Case 2a, rejected by dbx
+ with u_boot_console.log.section('Test Case 3a'):
+ # Test Case 3a, rejected by dbx
output = u_boot_console.run_command_list([
'host bind 0 %s' % disk_img,
'fatload host 0:1 4000000 db.auth',
@@ -84,30 +102,148 @@ class TestEfiSignedImage(object):
'setenv -e -nv -bs -rt -at -i 4000000,$filesize KEK',
'fatload host 0:1 4000000 PK.auth',
'setenv -e -nv -bs -rt -at -i 4000000,$filesize PK'])
- assert(not 'Failed to set EFI variable' in ''.join(output))
+ assert 'Failed to set EFI variable' not in ''.join(output)
output = u_boot_console.run_command_list([
'efidebug boot add 1 HELLO host 0:1 /helloworld.efi.signed ""',
'efidebug boot next 1',
- 'bootefi bootmgr'])
- assert('\'HELLO\' failed' in ''.join(output))
+ 'efidebug test bootmgr'])
+ assert '\'HELLO\' failed' in ''.join(output)
+ assert 'efi_start_image() returned: 26' in ''.join(output)
+
+ with u_boot_console.log.section('Test Case 3b'):
+ # Test Case 3b, rejected by dbx even if db allows
+ output = u_boot_console.run_command_list([
+ 'fatload host 0:1 4000000 db.auth',
+ 'setenv -e -nv -bs -rt -at -i 4000000,$filesize db'])
+ assert 'Failed to set EFI variable' not in ''.join(output)
output = u_boot_console.run_command_list([
'efidebug boot next 1',
'efidebug test bootmgr'])
- assert('efi_start_image() returned: 26' in ''.join(output))
- assert(not 'Hello, world!' in ''.join(output))
+ assert '\'HELLO\' failed' in ''.join(output)
+ assert 'efi_start_image() returned: 26' in ''.join(output)
- with u_boot_console.log.section('Test Case 2b'):
- # Test Case 2b, rejected by dbx even if db allows
+ def test_efi_signed_image_auth4(self, u_boot_console, efi_boot_env):
+ """
+ Test Case 4 - revoked by dbx (digest of TEST_db certificate in dbx)
+ """
+ u_boot_console.restart_uboot()
+ disk_img = efi_boot_env
+ with u_boot_console.log.section('Test Case 4'):
+ # Test Case 4, rejected by dbx
output = u_boot_console.run_command_list([
+ 'host bind 0 %s' % disk_img,
+ 'fatload host 0:1 4000000 dbx_hash.auth',
+ 'setenv -e -nv -bs -rt -at -i 4000000,$filesize dbx',
'fatload host 0:1 4000000 db.auth',
- 'setenv -e -nv -bs -rt -at -i 4000000,$filesize db'])
- assert(not 'Failed to set EFI variable' in ''.join(output))
+ 'setenv -e -nv -bs -rt -at -i 4000000,$filesize db',
+ 'fatload host 0:1 4000000 KEK.auth',
+ 'setenv -e -nv -bs -rt -at -i 4000000,$filesize KEK',
+ 'fatload host 0:1 4000000 PK.auth',
+ 'setenv -e -nv -bs -rt -at -i 4000000,$filesize PK'])
+ assert 'Failed to set EFI variable' not in ''.join(output)
+ output = u_boot_console.run_command_list([
+ 'efidebug boot add 1 HELLO host 0:1 /helloworld.efi.signed ""',
+ 'efidebug boot next 1',
+ 'efidebug test bootmgr'])
+ assert '\'HELLO\' failed' in ''.join(output)
+ assert 'efi_start_image() returned: 26' in ''.join(output)
+
+ def test_efi_signed_image_auth5(self, u_boot_console, efi_boot_env):
+ """
+ Test Case 5 - multiple signatures
+ one signed with TEST_db, and
+ one signed with TEST_db1
+ """
+ u_boot_console.restart_uboot()
+ disk_img = efi_boot_env
+ with u_boot_console.log.section('Test Case 5a'):
+ # Test Case 5a, rejected if any of signatures is not verified
output = u_boot_console.run_command_list([
+ 'host bind 0 %s' % disk_img,
+ 'fatload host 0:1 4000000 db.auth',
+ 'setenv -e -nv -bs -rt -at -i 4000000,$filesize db',
+ 'fatload host 0:1 4000000 KEK.auth',
+ 'setenv -e -nv -bs -rt -at -i 4000000,$filesize KEK',
+ 'fatload host 0:1 4000000 PK.auth',
+ 'setenv -e -nv -bs -rt -at -i 4000000,$filesize PK'])
+ assert 'Failed to set EFI variable' not in ''.join(output)
+ output = u_boot_console.run_command_list([
+ 'efidebug boot add 1 HELLO host 0:1 /helloworld.efi.signed_2sigs ""',
+ 'efidebug boot next 1',
+ 'efidebug test bootmgr'])
+ assert '\'HELLO\' failed' in ''.join(output)
+ assert 'efi_start_image() returned: 26' in ''.join(output)
+
+ with u_boot_console.log.section('Test Case 5b'):
+ # Test Case 5b, authenticated if both signatures are verified
+ output = u_boot_console.run_command_list([
+ 'fatload host 0:1 4000000 db1.auth',
+ 'setenv -e -nv -bs -rt -at -a -i 4000000,$filesize db'])
+ assert 'Failed to set EFI variable' not in ''.join(output)
+ output = u_boot_console.run_command_list([
+ 'efidebug boot add 1 HELLO host 0:1 /helloworld.efi.signed_2sigs ""',
'efidebug boot next 1',
'bootefi bootmgr'])
- assert('\'HELLO\' failed' in ''.join(output))
+ assert 'Hello, world!' in ''.join(output)
+
+ with u_boot_console.log.section('Test Case 5c'):
+ # Test Case 5c, rejected if any of signatures is revoked
+ output = u_boot_console.run_command_list([
+ 'fatload host 0:1 4000000 dbx_hash1.auth',
+ 'setenv -e -nv -bs -rt -at -i 4000000,$filesize dbx'])
+ assert 'Failed to set EFI variable' not in ''.join(output)
output = u_boot_console.run_command_list([
+ 'efidebug boot add 1 HELLO host 0:1 /helloworld.efi.signed_2sigs ""',
'efidebug boot next 1',
'efidebug test bootmgr'])
- assert('efi_start_image() returned: 26' in ''.join(output))
- assert(not 'Hello, world!' in ''.join(output))
+ assert '\'HELLO\' failed' in ''.join(output)
+ assert 'efi_start_image() returned: 26' in ''.join(output)
+
+ def test_efi_signed_image_auth6(self, u_boot_console, efi_boot_env):
+ """
+ Test Case 6 - using digest of signed image in database
+ """
+ u_boot_console.restart_uboot()
+ disk_img = efi_boot_env
+ with u_boot_console.log.section('Test Case 6a'):
+ # Test Case 6a, verified by image's digest in db
+ output = u_boot_console.run_command_list([
+ 'host bind 0 %s' % disk_img,
+ 'fatload host 0:1 4000000 db_hello_signed.auth',
+ 'setenv -e -nv -bs -rt -at -i 4000000,$filesize db',
+ 'fatload host 0:1 4000000 KEK.auth',
+ 'setenv -e -nv -bs -rt -at -i 4000000,$filesize KEK',
+ 'fatload host 0:1 4000000 PK.auth',
+ 'setenv -e -nv -bs -rt -at -i 4000000,$filesize PK'])
+ assert 'Failed to set EFI variable' not in ''.join(output)
+ output = u_boot_console.run_command_list([
+ 'efidebug boot add 1 HELLO host 0:1 /helloworld.efi.signed ""',
+ 'efidebug boot next 1',
+ 'bootefi bootmgr'])
+ assert 'Hello, world!' in ''.join(output)
+
+ with u_boot_console.log.section('Test Case 6b'):
+ # Test Case 6b, rejected by TEST_db certificate in dbx
+ output = u_boot_console.run_command_list([
+ 'fatload host 0:1 4000000 dbx_db.auth',
+ 'setenv -e -nv -bs -rt -at -i 4000000,$filesize dbx'])
+ assert 'Failed to set EFI variable' not in ''.join(output)
+ output = u_boot_console.run_command_list([
+ 'efidebug boot next 1',
+ 'efidebug test bootmgr'])
+ assert '\'HELLO\' failed' in ''.join(output)
+ assert 'efi_start_image() returned: 26' in ''.join(output)
+
+ with u_boot_console.log.section('Test Case 6c'):
+ # Test Case 6c, rejected by image's digest in dbx
+ output = u_boot_console.run_command_list([
+ 'fatload host 0:1 4000000 db.auth',
+ 'setenv -e -nv -bs -rt -at -i 4000000,$filesize db',
+ 'fatload host 0:1 4000000 dbx_hello_signed.auth',
+ 'setenv -e -nv -bs -rt -at -i 4000000,$filesize dbx'])
+ assert 'Failed to set EFI variable' not in ''.join(output)
+ output = u_boot_console.run_command_list([
+ 'efidebug boot next 1',
+ 'efidebug test bootmgr'])
+ assert '\'HELLO\' failed' in ''.join(output)
+ assert 'efi_start_image() returned: 26' in ''.join(output)
diff --git a/test/py/tests/test_efi_secboot/test_unsigned.py b/test/py/tests/test_efi_secboot/test_unsigned.py
index c42c5ddc477..c4c3f4c2023 100644
--- a/test/py/tests/test_efi_secboot/test_unsigned.py
+++ b/test/py/tests/test_efi_secboot/test_unsigned.py
@@ -9,7 +9,7 @@ This test verifies image authentication for unsigned images.
"""
import pytest
-from defs import *
+
@pytest.mark.boardspec('sandbox')
@pytest.mark.buildconfigspec('efi_secure_boot')
@@ -28,22 +28,22 @@ class TestEfiUnsignedImage(object):
# Test Case 1
output = u_boot_console.run_command_list([
'host bind 0 %s' % disk_img,
- 'fatload host 0:1 4000000 KEK.auth',
- 'setenv -e -nv -bs -rt -at -i 4000000,$filesize KEK',
- 'fatload host 0:1 4000000 PK.auth',
- 'setenv -e -nv -bs -rt -at -i 4000000,$filesize PK'])
- assert(not 'Failed to set EFI variable' in ''.join(output))
+ 'fatload host 0:1 4000000 KEK.auth',
+ 'setenv -e -nv -bs -rt -at -i 4000000,$filesize KEK',
+ 'fatload host 0:1 4000000 PK.auth',
+ 'setenv -e -nv -bs -rt -at -i 4000000,$filesize PK'])
+ assert 'Failed to set EFI variable' not in ''.join(output)
output = u_boot_console.run_command_list([
'efidebug boot add 1 HELLO host 0:1 /helloworld.efi ""',
'efidebug boot next 1',
'bootefi bootmgr'])
- assert('\'HELLO\' failed' in ''.join(output))
+ assert '\'HELLO\' failed' in ''.join(output)
output = u_boot_console.run_command_list([
'efidebug boot next 1',
'efidebug test bootmgr'])
- assert('efi_start_image() returned: 26' in ''.join(output))
- assert(not 'Hello, world!' in ''.join(output))
+ assert 'efi_start_image() returned: 26' in ''.join(output)
+ assert 'Hello, world!' not in ''.join(output)
def test_efi_unsigned_image_auth2(self, u_boot_console, efi_boot_env):
"""
@@ -55,19 +55,19 @@ class TestEfiUnsignedImage(object):
# Test Case 2
output = u_boot_console.run_command_list([
'host bind 0 %s' % disk_img,
- 'fatload host 0:1 4000000 db_hello.auth',
- 'setenv -e -nv -bs -rt -at -i 4000000,$filesize db',
- 'fatload host 0:1 4000000 KEK.auth',
- 'setenv -e -nv -bs -rt -at -i 4000000,$filesize KEK',
- 'fatload host 0:1 4000000 PK.auth',
- 'setenv -e -nv -bs -rt -at -i 4000000,$filesize PK'])
- assert(not 'Failed to set EFI variable' in ''.join(output))
+ 'fatload host 0:1 4000000 db_hello.auth',
+ 'setenv -e -nv -bs -rt -at -i 4000000,$filesize db',
+ 'fatload host 0:1 4000000 KEK.auth',
+ 'setenv -e -nv -bs -rt -at -i 4000000,$filesize KEK',
+ 'fatload host 0:1 4000000 PK.auth',
+ 'setenv -e -nv -bs -rt -at -i 4000000,$filesize PK'])
+ assert 'Failed to set EFI variable' not in ''.join(output)
output = u_boot_console.run_command_list([
'efidebug boot add 1 HELLO host 0:1 /helloworld.efi ""',
'efidebug boot next 1',
'bootefi bootmgr'])
- assert('Hello, world!' in ''.join(output))
+ assert 'Hello, world!' in ''.join(output)
def test_efi_unsigned_image_auth3(self, u_boot_console, efi_boot_env):
"""
@@ -79,39 +79,39 @@ class TestEfiUnsignedImage(object):
# Test Case 3a, rejected by dbx
output = u_boot_console.run_command_list([
'host bind 0 %s' % disk_img,
- 'fatload host 0:1 4000000 db_hello.auth',
- 'setenv -e -nv -bs -rt -at -i 4000000,$filesize dbx',
- 'fatload host 0:1 4000000 KEK.auth',
- 'setenv -e -nv -bs -rt -at -i 4000000,$filesize KEK',
- 'fatload host 0:1 4000000 PK.auth',
- 'setenv -e -nv -bs -rt -at -i 4000000,$filesize PK'])
- assert(not 'Failed to set EFI variable' in ''.join(output))
+ 'fatload host 0:1 4000000 db_hello.auth',
+ 'setenv -e -nv -bs -rt -at -i 4000000,$filesize dbx',
+ 'fatload host 0:1 4000000 KEK.auth',
+ 'setenv -e -nv -bs -rt -at -i 4000000,$filesize KEK',
+ 'fatload host 0:1 4000000 PK.auth',
+ 'setenv -e -nv -bs -rt -at -i 4000000,$filesize PK'])
+ assert 'Failed to set EFI variable' not in ''.join(output)
output = u_boot_console.run_command_list([
'efidebug boot add 1 HELLO host 0:1 /helloworld.efi ""',
'efidebug boot next 1',
'bootefi bootmgr'])
- assert('\'HELLO\' failed' in ''.join(output))
+ assert '\'HELLO\' failed' in ''.join(output)
output = u_boot_console.run_command_list([
'efidebug boot next 1',
'efidebug test bootmgr'])
- assert('efi_start_image() returned: 26' in ''.join(output))
- assert(not 'Hello, world!' in ''.join(output))
+ assert 'efi_start_image() returned: 26' in ''.join(output)
+ assert 'Hello, world!' not in ''.join(output)
with u_boot_console.log.section('Test Case 3b'):
# Test Case 3b, rejected by dbx even if db allows
output = u_boot_console.run_command_list([
- 'fatload host 0:1 4000000 db_hello.auth',
- 'setenv -e -nv -bs -rt -at -i 4000000,$filesize db'])
- assert(not 'Failed to set EFI variable' in ''.join(output))
+ 'fatload host 0:1 4000000 db_hello.auth',
+ 'setenv -e -nv -bs -rt -at -i 4000000,$filesize db'])
+ assert 'Failed to set EFI variable' not in ''.join(output)
output = u_boot_console.run_command_list([
'efidebug boot add 1 HELLO host 0:1 /helloworld.efi ""',
'efidebug boot next 1',
'bootefi bootmgr'])
- assert('\'HELLO\' failed' in ''.join(output))
+ assert '\'HELLO\' failed' in ''.join(output)
output = u_boot_console.run_command_list([
'efidebug boot next 1',
'efidebug test bootmgr'])
- assert('efi_start_image() returned: 26' in ''.join(output))
- assert(not 'Hello, world!' in ''.join(output))
+ assert 'efi_start_image() returned: 26' in ''.join(output)
+ assert 'Hello, world!' not in ''.join(output)