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/Kconfig8
-rw-r--r--cmd/Makefile1
-rw-r--r--cmd/fitupd.c30
-rw-r--r--cmd/lsblk.c2
-rw-r--r--cmd/nvedit.c7
-rw-r--r--cmd/nvedit_efi.c128
-rw-r--r--configs/da850evm_direct_nor_defconfig1
-rw-r--r--configs/omap3_beagle_defconfig3
-rw-r--r--configs/sandbox_defconfig1
-rw-r--r--doc/README.davinci10
-rw-r--r--doc/README.dfutftp2
-rw-r--r--doc/README.update5
-rw-r--r--doc/api/efi.rst2
-rw-r--r--doc/uefi/uefi.rst9
-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/mmc.c5
-rw-r--r--drivers/mmc/mmc_spi.c52
-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/asm-generic/sections.h2
-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.h236
-rw-r--r--include/linux/soc/ti/k3-navss-ringacc.h4
-rw-r--r--include/mm_communication.h43
-rw-r--r--include/u-boot/rsa.h3
-rw-r--r--lib/efi_loader/Kconfig55
-rw-r--r--lib/efi_loader/Makefile9
-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.c322
-rw-r--r--lib/efi_loader/efi_var_file.c233
-rw-r--r--lib/efi_loader/efi_var_mem.c266
-rw-r--r--lib/efi_loader/efi_var_seed.S17
-rw-r--r--lib/efi_loader/efi_variable.c951
-rw-r--r--lib/efi_loader/efi_variable_tee.c282
-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_loader.py16
-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
72 files changed, 3350 insertions, 2270 deletions
diff --git a/.azure-pipelines.yml b/.azure-pipelines.yml
index 98e8a4fe14..97c89fc067 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 23599b97c0..ae91252a00 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 d0746955b4..d2f864669d 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 bc9a87210d..1355685839 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 a7e5eb0553..d9ff3ed47b 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 7b01e4204f..6e748bfebb 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 2eed50aa5a..e6c99ab698 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 9695b2236e..63bf060616 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 f6b63db349..f7afef610c 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 a3b0f8bf09..c91aeb8dbf 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 9139ad87d4..9ccd566da3 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/Kconfig b/cmd/Kconfig
index 846c905c9c..bfe6c163dc 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -378,6 +378,7 @@ config CMD_BOOTEFI_HELLO_COMPILE
config CMD_BOOTEFI_HELLO
bool "Allow booting a standard EFI hello world for testing"
depends on CMD_BOOTEFI_HELLO_COMPILE
+ default y if CMD_BOOTEFI_SELFTEST
help
This adds a standard EFI hello world application to U-Boot so that
it can be used with the 'bootefi hello' command. This is useful
@@ -489,13 +490,6 @@ config CMD_SPL_WRITE_SIZE
flash used by Falcon-mode boot. See the documentation until CMD_SPL
for detail.
-config CMD_FITUPD
- bool "fitImage update command"
- depends on UPDATE_TFTP
- help
- Implements the 'fitupd' command, which allows to automatically
- store software updates present on a TFTP server in NOR Flash
-
config CMD_THOR_DOWNLOAD
bool "thor - TIZEN 'thor' download"
select DFU
diff --git a/cmd/Makefile b/cmd/Makefile
index dc412d1106..7952138dc2 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -62,7 +62,6 @@ obj-$(CONFIG_CMD_EXT4) += ext4.o
obj-$(CONFIG_CMD_EXT2) += ext2.o
obj-$(CONFIG_CMD_FAT) += fat.o
obj-$(CONFIG_CMD_FDT) += fdt.o
-obj-$(CONFIG_CMD_FITUPD) += fitupd.o
obj-$(CONFIG_CMD_FLASH) += flash.o
obj-$(CONFIG_CMD_FPGA) += fpga.o
obj-$(CONFIG_CMD_FPGAD) += fpgad.o
diff --git a/cmd/fitupd.c b/cmd/fitupd.c
deleted file mode 100644
index 0f490c58fc..0000000000
--- a/cmd/fitupd.c
+++ /dev/null
@@ -1,30 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * (C) Copyright 2011
- * Andreas Pretzsch, carpe noctem engineering, apr@cn-eng.de
- */
-
-#include <common.h>
-#include <command.h>
-#include <net.h>
-
-static int do_fitupd(struct cmd_tbl *cmdtp, int flag, int argc,
- char *const argv[])
-{
- ulong addr = 0UL;
-
- if (argc > 2)
- return CMD_RET_USAGE;
-
- if (argc == 2)
- addr = simple_strtoul(argv[1], NULL, 16);
-
- return update_tftp(addr, NULL, NULL);
-}
-
-U_BOOT_CMD(fitupd, 2, 0, do_fitupd,
- "update from FIT image",
- "[addr]\n"
- "\t- run update from FIT image at addr\n"
- "\t or from tftp 'updatefile'"
-);
diff --git a/cmd/lsblk.c b/cmd/lsblk.c
index ece8bbf108..653dffce04 100644
--- a/cmd/lsblk.c
+++ b/cmd/lsblk.c
@@ -5,6 +5,8 @@
*/
#include <common.h>
+#include <blk.h>
+#include <command.h>
#include <dm.h>
static int do_lsblk(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[])
diff --git a/cmd/nvedit.c b/cmd/nvedit.c
index 49338b4d36..ca0be92fc3 100644
--- a/cmd/nvedit.c
+++ b/cmd/nvedit.c
@@ -1410,7 +1410,7 @@ static char env_help_text[] =
#endif
"env print [-a | name ...] - print environment\n"
#if defined(CONFIG_CMD_NVEDIT_EFI)
- "env print -e [-guid guid|-all][-n] [name ...] - print UEFI environment\n"
+ "env print -e [-guid guid] [-n] [name ...] - print UEFI environment\n"
#endif
#if defined(CONFIG_CMD_RUN)
"env run var [...] - run commands in an environment variable\n"
@@ -1452,8 +1452,9 @@ U_BOOT_CMD_COMPLETE(
"print environment variables",
"[-a]\n - print [all] values of all environment variables\n"
#if defined(CONFIG_CMD_NVEDIT_EFI)
- "printenv -e [-guid guid|-all][-n] [name ...]\n"
+ "printenv -e [-guid guid][-n] [name ...]\n"
" - print UEFI variable 'name' or all the variables\n"
+ " \"-guid\": GUID xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n"
" \"-n\": suppress dumping variable's value\n"
#endif
"printenv name ...\n"
@@ -1487,7 +1488,7 @@ U_BOOT_CMD_COMPLETE(
"-e [-guid guid][-nv][-bs][-rt][-at][-a][-v]\n"
" [-i addr,size name], or [name [value ...]]\n"
" - set UEFI variable 'name' to 'value' ...'\n"
- " \"-guid\": set vendor guid\n"
+ " \"-guid\": GUID xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n"
" \"-nv\": set non-volatile attribute\n"
" \"-bs\": set boot-service attribute\n"
" \"-rt\": set runtime attribute\n"
diff --git a/cmd/nvedit_efi.c b/cmd/nvedit_efi.c
index 29cad38e19..8e31f43e1f 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 {
@@ -49,8 +52,7 @@ static const struct {
{EFI_CERT_TYPE_PKCS7_GUID, "EFI_CERT_TYPE_PKCS7_GUID"},
};
-/* "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" */
-static char unknown_guid[37];
+static const char unknown_guid[] = "";
/**
* efi_guid_to_str() - convert guid to readable name
@@ -68,9 +70,6 @@ static const char *efi_guid_to_str(const efi_guid_t *guid)
if (!guidcmp(guid, &efi_guid_text[i].guid))
return efi_guid_text[i].text;
- uuid_bin_to_str((unsigned char *)guid->b, unknown_guid,
- UUID_STR_FORMAT_GUID);
-
return unknown_guid;
}
@@ -87,20 +86,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 +110,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 %pUl %s\n", name, guid, 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);
}
@@ -128,50 +132,6 @@ out:
free(data);
}
-/**
- * efi_dump_vars() - show information about named UEFI variables
- *
- * @argc: Number of arguments (variables)
- * @argv: Argument (variable name) array
- * @verbose: if true, dump data
- * Return: CMD_RET_SUCCESS on success, or CMD_RET_RET_FAILURE
- *
- * Show information encoded in named UEFI variables
- */
-static int efi_dump_vars(int argc, char *const argv[],
- const efi_guid_t *guid, bool verbose)
-{
- u16 *var_name16, *p;
- efi_uintn_t buf_size, size;
-
- buf_size = 128;
- var_name16 = malloc(buf_size);
- if (!var_name16)
- return CMD_RET_FAILURE;
-
- for (; argc > 0; argc--, argv++) {
- size = (utf8_utf16_strlen(argv[0]) + 1) * sizeof(u16);
- if (buf_size < size) {
- buf_size = size;
- p = realloc(var_name16, buf_size);
- if (!p) {
- free(var_name16);
- return CMD_RET_FAILURE;
- }
- var_name16 = p;
- }
-
- p = var_name16;
- utf8_utf16_strcpy(&p, argv[0]);
-
- efi_dump_single_var(var_name16, guid, verbose);
- }
-
- free(var_name16);
-
- return CMD_RET_SUCCESS;
-}
-
static bool match_name(int argc, char *const argv[], u16 *var_name16)
{
char *buf, *p;
@@ -217,10 +177,7 @@ static int efi_dump_var_all(int argc, char *const argv[],
efi_uintn_t buf_size, size;
efi_guid_t guid;
efi_status_t ret;
-
- if (argc && guid_p)
- /* simplified case */
- return efi_dump_vars(argc, argv, guid_p, verbose);
+ bool match = false;
buf_size = 128;
var_name16 = malloc(buf_size);
@@ -251,13 +208,18 @@ static int efi_dump_var_all(int argc, char *const argv[],
return CMD_RET_FAILURE;
}
- if ((!guid_p || !guidcmp(guid_p, &guid)) &&
- (!argc || match_name(argc, argv, var_name16)))
+ if (guid_p && guidcmp(guid_p, &guid))
+ continue;
+ if (!argc || match_name(argc, argv, var_name16)) {
+ match = true;
efi_dump_single_var(var_name16, &guid, verbose);
+ }
}
-
free(var_name16);
+ if (!match && argc == 1)
+ printf("Error: \"%s\" not defined\n", argv[0]);
+
return CMD_RET_SUCCESS;
}
@@ -278,9 +240,8 @@ static int efi_dump_var_all(int argc, char *const argv[],
int do_env_print_efi(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
{
- efi_guid_t guid;
- const efi_guid_t *guid_p;
- bool default_guid, guid_any, verbose;
+ const efi_guid_t *guid_p = NULL;
+ bool verbose = true;
efi_status_t ret;
/* Initialize EFI drivers */
@@ -291,31 +252,18 @@ int do_env_print_efi(struct cmd_tbl *cmdtp, int flag, int argc,
return CMD_RET_FAILURE;
}
- default_guid = true;
- guid_any = false;
- verbose = true;
for (argc--, argv++; argc > 0 && argv[0][0] == '-'; argc--, argv++) {
if (!strcmp(argv[0], "-guid")) {
- if (argc == 1)
- return CMD_RET_USAGE;
+ efi_guid_t guid;
- /* -a already specified */
- if (!default_guid && guid_any)
+ if (argc == 1)
return CMD_RET_USAGE;
-
argc--;
argv++;
if (uuid_str_to_bin(argv[0], guid.b,
UUID_STR_FORMAT_GUID))
return CMD_RET_USAGE;
- default_guid = false;
- } else if (!strcmp(argv[0], "-all")) {
- /* -guid already specified */
- if (!default_guid && !guid_any)
- return CMD_RET_USAGE;
-
- guid_any = true;
- default_guid = false;
+ guid_p = (const efi_guid_t *)guid.b;
} else if (!strcmp(argv[0], "-n")) {
verbose = false;
} else {
@@ -323,13 +271,6 @@ int do_env_print_efi(struct cmd_tbl *cmdtp, int flag, int argc,
}
}
- if (guid_any)
- guid_p = NULL;
- else if (default_guid)
- guid_p = &efi_global_variable_guid;
- else
- guid_p = (const efi_guid_t *)guid.b;
-
/* enumerate and show all UEFI variables */
return efi_dump_var_all(argc, argv, guid_p, verbose);
}
@@ -510,8 +451,7 @@ int do_env_set_efi(struct cmd_tbl *cmdtp, int flag, int argc,
argv++;
if (uuid_str_to_bin(argv[0], guid.b,
UUID_STR_FORMAT_GUID)) {
- printf("## Guid not specified or in XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX format\n");
- return CMD_RET_FAILURE;
+ return CMD_RET_USAGE;
}
default_guid = false;
} else if (!strcmp(argv[0], "-bs")) {
@@ -559,8 +499,8 @@ int do_env_set_efi(struct cmd_tbl *cmdtp, int flag, int argc,
}
if (verbose) {
- printf("GUID: %s\n", efi_guid_to_str((const efi_guid_t *)
- &guid));
+ printf("GUID: %pUl %s\n", &guid,
+ efi_guid_to_str((const efi_guid_t *)&guid));
printf("Attributes: 0x%x\n", attributes);
}
@@ -592,8 +532,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 36ef122ba3..3924895204 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 af5b8ea872..b08ffc062d 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/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 9b74e404bb..d43d78df6f 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -48,6 +48,7 @@ CONFIG_CMD_GPT=y
CONFIG_CMD_GPT_RENAME=y
CONFIG_CMD_IDE=y
CONFIG_CMD_I2C=y
+CONFIG_CMD_LSBLK=y
CONFIG_CMD_OSD=y
CONFIG_CMD_PCI=y
CONFIG_CMD_READ=y
diff --git a/doc/README.davinci b/doc/README.davinci
index 6522c24eea..607531af2a 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/README.dfutftp b/doc/README.dfutftp
index 127d2d6abc..a3341bbb61 100644
--- a/doc/README.dfutftp
+++ b/doc/README.dfutftp
@@ -42,8 +42,6 @@ for USB based DFU (CONFIG_DFU_*) and DFU TFTP update
The "dfu" command has been extended to support transfer via TFTP - one
needs to type for example "dfu tftp 0 mmc 0"
-This feature does not depend on "fitupd" command enabled.
-
As of this writing (SHA1:8d77576371381ade83de475bb639949b44941e8c v2015.10-rc2)
the update.c code is not enabled (CONFIG_UPDATE_TFTP) by any board in the
contemporary u-boot tree.
diff --git a/doc/README.update b/doc/README.update
index d37f2c4d4a..bf4379279e 100644
--- a/doc/README.update
+++ b/doc/README.update
@@ -51,11 +51,6 @@ the mkimage tool. dtc tool with support for binary includes, e.g. in version
to be prepared. Refer to the doc/uImage.FIT/ directory for more details on FIT
images.
-This mechanism can be also triggered by the command "fitupd".
-If an optional, non-zero address is provided as argument, the TFTP transfer
-is skipped and the image at this address is used.
-The fitupd command is enabled by CONFIG_CMD_FITUPD.
-
Example .its files
------------------
diff --git a/doc/api/efi.rst b/doc/api/efi.rst
index d5114f05b3..cb2a1c897e 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/doc/uefi/uefi.rst b/doc/uefi/uefi.rst
index 03d6fd0c6a..a72e729cc8 100644
--- a/doc/uefi/uefi.rst
+++ b/doc/uefi/uefi.rst
@@ -188,6 +188,15 @@ on the sandbox
cd <U-Boot source directory>
pytest.py test/py/tests/test_efi_secboot/test_signed.py --bd sandbox
+UEFI binaries may be signed by Microsoft using the following certificates:
+
+* KEK: Microsoft Corporation KEK CA 2011
+ http://go.microsoft.com/fwlink/?LinkId=321185.
+* db: Microsoft Windows Production PCA 2011
+ http://go.microsoft.com/fwlink/p/?linkid=321192.
+* db: Microsoft Corporation UEFI CA 2011
+ http://go.microsoft.com/fwlink/p/?linkid=321194.
+
Using OP-TEE for EFI variables
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/drivers/dma/ti/Kconfig b/drivers/dma/ti/Kconfig
index 3d5498326c..9cbd5f334d 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 de2f9ac91a..4ea9c626cc 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 0000000000..f95d99cfd3
--- /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 0000000000..105ffd946f
--- /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 0000000000..d3a38322b1
--- /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 0000000000..b5c92b2829
--- /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 0000000000..53c61b4595
--- /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 2ce16c8e27..57d9fbfabb 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/mmc.c b/drivers/mmc/mmc.c
index 50f47d4ba2..7b5c55be7d 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -1753,6 +1753,11 @@ static int sd_select_mode_and_width(struct mmc *mmc, uint card_caps)
mmc_set_bus_width(mmc, 1);
mmc_select_mode(mmc, MMC_LEGACY);
mmc_set_clock(mmc, mmc->tran_speed, MMC_CLK_ENABLE);
+#if CONFIG_IS_ENABLED(MMC_WRITE)
+ err = sd_read_ssr(mmc);
+ if (err)
+ pr_warn("unable to read ssr\n");
+#endif
return 0;
}
diff --git a/drivers/mmc/mmc_spi.c b/drivers/mmc/mmc_spi.c
index e76ab54838..50fcd32674 100644
--- a/drivers/mmc/mmc_spi.c
+++ b/drivers/mmc/mmc_spi.c
@@ -59,6 +59,7 @@
#define CMD_TIMEOUT 8
#define READ_TIMEOUT 3000000 /* 1 sec */
#define WRITE_TIMEOUT 3000000 /* 1 sec */
+#define R1B_TIMEOUT 3000000 /* 1 sec */
struct mmc_spi_plat {
struct mmc_config cfg;
@@ -72,7 +73,7 @@ struct mmc_spi_priv {
static int mmc_spi_sendcmd(struct udevice *dev,
ushort cmdidx, u32 cmdarg, u32 resp_type,
u8 *resp, u32 resp_size,
- bool resp_match, u8 resp_match_value)
+ bool resp_match, u8 resp_match_value, bool r1b)
{
int i, rpos = 0, ret = 0;
u8 cmdo[7], r;
@@ -105,12 +106,14 @@ static int mmc_spi_sendcmd(struct udevice *dev,
if (resp_match) {
r = ~resp_match_value;
i = CMD_TIMEOUT;
- while (i--) {
+ while (i) {
ret = dm_spi_xfer(dev, 1 * 8, NULL, &r, 0);
if (ret)
return ret;
debug(" resp%d=0x%x", rpos, r);
rpos++;
+ i--;
+
if (r == resp_match_value)
break;
}
@@ -131,6 +134,24 @@ static int mmc_spi_sendcmd(struct udevice *dev,
resp[i] = r;
}
+ if (r1b == true) {
+ i = R1B_TIMEOUT;
+ while (i) {
+ ret = dm_spi_xfer(dev, 1 * 8, NULL, &r, 0);
+ if (ret)
+ return ret;
+
+ debug(" resp%d=0x%x", rpos, r);
+ rpos++;
+ i--;
+
+ if (r)
+ break;
+ }
+ if (!i)
+ return -ETIMEDOUT;
+ }
+
debug("\n");
return 0;
@@ -263,8 +284,8 @@ static int dm_mmc_spi_request(struct udevice *dev, struct mmc_cmd *cmd,
int i, multi, ret = 0;
u8 *resp = NULL;
u32 resp_size = 0;
- bool resp_match = false;
- u8 resp8 = 0, resp40[5] = { 0 }, resp_match_value = 0;
+ bool resp_match = false, r1b = false;
+ u8 resp8 = 0, resp16[2] = { 0 }, resp40[5] = { 0 }, resp_match_value = 0;
dm_spi_claim_bus(dev);
@@ -289,20 +310,33 @@ static int dm_mmc_spi_request(struct udevice *dev, struct mmc_cmd *cmd,
resp_size = sizeof(resp40);
break;
case MMC_CMD_SEND_STATUS:
+ resp = (u8 *)&resp16[0];
+ resp_size = sizeof(resp16);
+ break;
case MMC_CMD_SET_BLOCKLEN:
case MMC_CMD_SPI_CRC_ON_OFF:
- case MMC_CMD_STOP_TRANSMISSION:
resp = &resp8;
resp_size = sizeof(resp8);
resp_match = true;
resp_match_value = 0x0;
break;
+ case MMC_CMD_STOP_TRANSMISSION:
+ case MMC_CMD_ERASE:
+ resp = &resp8;
+ resp_size = sizeof(resp8);
+ r1b = true;
+ break;
case MMC_CMD_SEND_CSD:
case MMC_CMD_SEND_CID:
case MMC_CMD_READ_SINGLE_BLOCK:
case MMC_CMD_READ_MULTIPLE_BLOCK:
case MMC_CMD_WRITE_SINGLE_BLOCK:
case MMC_CMD_WRITE_MULTIPLE_BLOCK:
+ case MMC_CMD_APP_CMD:
+ case SD_CMD_ERASE_WR_BLK_START:
+ case SD_CMD_ERASE_WR_BLK_END:
+ resp = &resp8;
+ resp_size = sizeof(resp8);
break;
default:
resp = &resp8;
@@ -313,7 +347,7 @@ static int dm_mmc_spi_request(struct udevice *dev, struct mmc_cmd *cmd,
};
ret = mmc_spi_sendcmd(dev, cmd->cmdidx, cmd->cmdarg, cmd->resp_type,
- resp, resp_size, resp_match, resp_match_value);
+ resp, resp_size, resp_match, resp_match_value, r1b);
if (ret)
goto done;
@@ -330,8 +364,10 @@ static int dm_mmc_spi_request(struct udevice *dev, struct mmc_cmd *cmd,
cmd->response[0] |= (uint)resp40[1] << 24;
break;
case MMC_CMD_SEND_STATUS:
- cmd->response[0] = (resp8 & 0xff) ?
- MMC_STATUS_ERROR : MMC_STATUS_RDY_FOR_DATA;
+ if (resp16[0] || resp16[1])
+ cmd->response[0] = MMC_STATUS_ERROR;
+ else
+ cmd->response[0] = MMC_STATUS_RDY_FOR_DATA;
break;
case MMC_CMD_SEND_CID:
case MMC_CMD_SEND_CSD:
diff --git a/drivers/mmc/omap_hsmmc.c b/drivers/mmc/omap_hsmmc.c
index 0e05fe4cfc..db1f85125f 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 85f3e49c05..971bdcdfda 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 ecc4b8b5a0..c48e9befe4 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 b16a39d3ff..a2682b5f46 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/asm-generic/sections.h b/include/asm-generic/sections.h
index 17a31ec788..0577238d60 100644
--- a/include/asm-generic/sections.h
+++ b/include/asm-generic/sections.h
@@ -25,6 +25,8 @@ extern char __initdata_begin[], __initdata_end[];
extern char __start_rodata[], __end_rodata[];
extern char __efi_helloworld_begin[];
extern char __efi_helloworld_end[];
+extern char __efi_var_file_begin[];
+extern char __efi_var_file_end[];
/* Start and end of .ctors section - used for constructor calls. */
extern char __ctors_start[], __ctors_end[];
diff --git a/include/configs/da850evm.h b/include/configs/da850evm.h
index 2bb4e47496..11aca4afe1 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 b8234da45a..906033a90e 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 670e1232b4..0000000000
--- 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 759d911875..5744f6aed8 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 fc9344c742..98944640be 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 0000000000..2c629e4dca
--- /dev/null
+++ b/include/efi_variable.h
@@ -0,0 +1,236 @@
+/* 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)
+
+enum efi_auth_var_type {
+ EFI_AUTH_VAR_NONE = 0,
+ EFI_AUTH_VAR_PK,
+ EFI_AUTH_VAR_KEK,
+ EFI_AUTH_VAR_DB,
+ EFI_AUTH_VAR_DBX,
+ EFI_AUTH_VAR_DBT,
+ EFI_AUTH_VAR_DBR,
+};
+
+/**
+ * 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
+
+/*
+ * This constant identifies the file format for storing UEFI variables in
+ * struct efi_var_file.
+ */
+#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, takes value %EFI_VAR_FILE_MAGIC
+ * @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_restore() - restore EFI variables from buffer
+ *
+ * @buf: buffer
+ * Return: status code
+ */
+efi_status_t efi_var_restore(struct efi_var_file *buf);
+
+/**
+ * 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);
+
+/**
+ * efi_init_secure_state - initialize secure boot state
+ *
+ * Return: status code
+ */
+efi_status_t efi_init_secure_state(void);
+
+/**
+ * efi_auth_var_get_type() - convert variable name and guid to enum
+ *
+ * @name: name of UEFI variable
+ * @guid: guid of UEFI variable
+ * Return: identifier for authentication related variables
+ */
+enum efi_auth_var_type efi_auth_var_get_type(u16 *name, const efi_guid_t *guid);
+
+#endif
diff --git a/include/linux/soc/ti/k3-navss-ringacc.h b/include/linux/soc/ti/k3-navss-ringacc.h
index 7b027f8bd4..9176277ff0 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/mm_communication.h b/include/mm_communication.h
index 193c4d1578..f9c05bb7f1 100644
--- a/include/mm_communication.h
+++ b/include/mm_communication.h
@@ -205,4 +205,47 @@ struct smm_variable_query_info {
u32 attr;
};
+#define VAR_CHECK_VARIABLE_PROPERTY_REVISION 0x0001
+#define VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY BIT(0)
+/**
+ * struct var_check_property - Used to store variable properties in StMM
+ *
+ * @revision: magic revision number for variable property checking
+ * @property: properties mask for the variable used in StMM.
+ * Currently RO flag is supported
+ * @attributes: variable attributes used in StMM checking when properties
+ * for a variable are enabled
+ * @minsize: minimum allowed size for variable payload checked against
+ * smm_variable_access->datasize in StMM
+ * @maxsize: maximum allowed size for variable payload checked against
+ * smm_variable_access->datasize in StMM
+ *
+ * Defined in EDK2 as VAR_CHECK_VARIABLE_PROPERTY.
+ */
+struct var_check_property {
+ u16 revision;
+ u16 property;
+ u32 attributes;
+ efi_uintn_t minsize;
+ efi_uintn_t maxsize;
+};
+
+/**
+ * struct smm_variable_var_check_property - Used to communicate variable
+ * properties with StMM
+ *
+ * @guid: vendor GUID
+ * @name_size: size of EFI name
+ * @property: variable properties struct
+ * @name: variable name
+ *
+ * Defined in EDK2 as SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY.
+ */
+struct smm_variable_var_check_property {
+ efi_guid_t guid;
+ efi_uintn_t name_size;
+ struct var_check_property property;
+ u16 name[];
+};
+
#endif /* _MM_COMMUNICATION_H_ */
diff --git a/include/u-boot/rsa.h b/include/u-boot/rsa.h
index a0bae495f0..bed1c097c2 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 6c9df3a767..6017ffe9a6 100644
--- a/lib/efi_loader/Kconfig
+++ b/lib/efi_loader/Kconfig
@@ -27,6 +27,52 @@ config EFI_LOADER
if EFI_LOADER
+choice
+ prompt "Store for non-volatile UEFI variables"
+ default EFI_VARIABLE_FILE_STORE
+ help
+ Select where non-volatile UEFI variables shall be stored.
+
+config EFI_VARIABLE_FILE_STORE
+ bool "Store non-volatile UEFI variables as file"
+ depends on FAT_WRITE
+ help
+ Select this option if you want non-volatile UEFI variables to be
+ stored as file /ubootefi.var on the EFI system partition.
+
+config EFI_MM_COMM_TEE
+ bool "UEFI variables storage service via OP-TEE"
+ depends on OPTEE
+ help
+ If OP-TEE is present and running StandAloneMM, dispatch all UEFI
+ variable related operations to that. The application will verify,
+ authenticate and store the variables on an RPMB.
+
+endchoice
+
+config EFI_VARIABLES_PRESEED
+ bool "Initial values for UEFI variables"
+ depends on EFI_VARIABLE_FILE_STORE
+ help
+ Include a file with the initial values for non-volatile UEFI variables
+ into the U-Boot binary. If this configuration option is set, changes
+ to authentication related variables (PK, KEK, db, dbx) are not
+ allowed.
+
+if EFI_VARIABLES_PRESEED
+
+config EFI_VAR_SEED_FILE
+ string "File with initial values of non-volatile UEFI variables"
+ default ubootefi.var
+ help
+ File with initial values of non-volatile UEFI variables. The file must
+ be in the same format as the storage in the EFI system partition. The
+ easiest way to create it is by setting the non-volatile variables in
+ U-Boot. If a relative file path is used, it is relative to the source
+ directory.
+
+endif
+
config EFI_GET_TIME
bool "GetTime() runtime service"
depends on DM_RTC
@@ -166,13 +212,4 @@ config EFI_SECURE_BOOT
it is signed with a trusted key. To do that, you need to install,
at least, PK, KEK and db.
-config EFI_MM_COMM_TEE
- bool "UEFI variables storage service via OP-TEE"
- depends on OPTEE
- default n
- help
- If OP-TEE is present and running StandAloneMM, dispatch all UEFI variable
- related operations to that. The application will verify, authenticate and
- store the variables on an RPMB.
-
endif
diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile
index 57c7e66ea0..441ac9432e 100644
--- a/lib/efi_loader/Makefile
+++ b/lib/efi_loader/Makefile
@@ -6,7 +6,7 @@
# This file only gets included with CONFIG_EFI_LOADER set, so all
# object inclusion implicitly depends on it
-asflags-y += -DHOST_ARCH="$(HOST_ARCH)"
+asflags-y += -DHOST_ARCH="$(HOST_ARCH)" -I.
ccflags-y += -DHOST_ARCH="$(HOST_ARCH)"
CFLAGS_efi_boottime.o += \
@@ -35,10 +35,14 @@ 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
+obj-$(CONFIG_EFI_VARIABLES_PRESEED) += efi_var_seed.o
endif
obj-y += efi_watchdog.o
obj-$(CONFIG_LCD) += efi_gop.o
@@ -50,3 +54,6 @@ obj-$(CONFIG_GENERATE_SMBIOS_TABLE) += efi_smbios.o
obj-$(CONFIG_EFI_RNG_PROTOCOL) += efi_rng.o
obj-$(CONFIG_EFI_LOAD_FILE2_INITRD) += efi_load_initrd.o
obj-y += efi_signature.o
+
+EFI_VAR_SEED_FILE := $(subst $\",,$(CONFIG_EFI_VAR_SEED_FILE))
+$(obj)/efi_var_seed.o: $(srctree)/$(EFI_VAR_SEED_FILE)
diff --git a/lib/efi_loader/efi_bootmgr.c b/lib/efi_loader/efi_bootmgr.c
index e268e9c4b8..e03198b57a 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 1591ad8300..0b16554ba2 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 06a2ebdb90..fef0bb870c 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 c0bd99b867..91a4551448 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 a3b05a4a9b..6196c0a06c 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 e05c471c61..fc0314e6d4 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 0000000000..ee2e67bc8c
--- /dev/null
+++ b/lib/efi_loader/efi_var_common.c
@@ -0,0 +1,322 @@
+// 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>
+
+enum efi_secure_mode {
+ EFI_MODE_SETUP,
+ EFI_MODE_USER,
+ EFI_MODE_AUDIT,
+ EFI_MODE_DEPLOYED,
+};
+
+struct efi_auth_var_name_type {
+ const u16 *name;
+ const efi_guid_t *guid;
+ const enum efi_auth_var_type type;
+};
+
+static const struct efi_auth_var_name_type name_type[] = {
+ {u"PK", &efi_global_variable_guid, EFI_AUTH_VAR_PK},
+ {u"KEK", &efi_global_variable_guid, EFI_AUTH_VAR_KEK},
+ {u"db", &efi_guid_image_security_database, EFI_AUTH_VAR_DB},
+ {u"dbx", &efi_guid_image_security_database, EFI_AUTH_VAR_DBX},
+ /* not used yet
+ {u"dbt", &efi_guid_image_security_database, EFI_AUTH_VAR_DBT},
+ {u"dbr", &efi_guid_image_security_database, EFI_AUTH_VAR_DBR},
+ */
+};
+
+static bool efi_secure_boot;
+static enum efi_secure_mode efi_secure_mode;
+
+/**
+ * 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);
+}
+
+/**
+ * efi_set_secure_state - modify secure boot state variables
+ * @secure_boot: value of SecureBoot
+ * @setup_mode: value of SetupMode
+ * @audit_mode: value of AuditMode
+ * @deployed_mode: value of DeployedMode
+ *
+ * Modify secure boot status related variables as indicated.
+ *
+ * Return: status code
+ */
+static efi_status_t efi_set_secure_state(u8 secure_boot, u8 setup_mode,
+ u8 audit_mode, u8 deployed_mode)
+{
+ 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;
+
+ 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_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_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_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;
+}
+
+/**
+ * efi_transfer_secure_state - handle a secure boot state transition
+ * @mode: new state
+ *
+ * Depending on @mode, secure boot related variables are updated.
+ * Those variables are *read-only* for users, efi_set_variable_int()
+ * is called here.
+ *
+ * Return: status code
+ */
+static efi_status_t efi_transfer_secure_state(enum efi_secure_mode mode)
+{
+ efi_status_t ret;
+
+ EFI_PRINT("Switching secure state from %d to %d\n", efi_secure_mode,
+ mode);
+
+ if (mode == EFI_MODE_DEPLOYED) {
+ ret = efi_set_secure_state(1, 0, 0, 1);
+ if (ret != EFI_SUCCESS)
+ goto err;
+ } else if (mode == EFI_MODE_AUDIT) {
+ 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;
+ } else if (mode == EFI_MODE_USER) {
+ ret = efi_set_secure_state(1, 0, 0, 0);
+ if (ret != EFI_SUCCESS)
+ goto err;
+ } else if (mode == EFI_MODE_SETUP) {
+ ret = efi_set_secure_state(0, 1, 0, 0);
+ if (ret != EFI_SUCCESS)
+ goto err;
+ } else {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ efi_secure_mode = mode;
+
+ return EFI_SUCCESS;
+
+err:
+ /* TODO: What action should be taken here? */
+ printf("ERROR: Secure state transition failed\n");
+ return ret;
+}
+
+efi_status_t efi_init_secure_state(void)
+{
+ enum efi_secure_mode mode = EFI_MODE_SETUP;
+ u8 efi_vendor_keys = 0;
+ efi_uintn_t size = 0;
+ efi_status_t ret;
+
+ 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;
+ }
+
+ ret = efi_transfer_secure_state(mode);
+ if (ret != EFI_SUCCESS)
+ return ret;
+
+ /* 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;
+}
+
+/**
+ * efi_secure_boot_enabled - return if secure boot is enabled or not
+ *
+ * Return: true if enabled, false if disabled
+ */
+bool efi_secure_boot_enabled(void)
+{
+ return efi_secure_boot;
+}
+
+enum efi_auth_var_type efi_auth_var_get_type(u16 *name, const efi_guid_t *guid)
+{
+ for (size_t i = 0; i < ARRAY_SIZE(name_type); ++i) {
+ if (!u16_strcmp(name, name_type[i].name) &&
+ !guidcmp(guid, name_type[i].guid))
+ return name_type[i].type;
+ }
+ return EFI_AUTH_VAR_NONE;
+}
diff --git a/lib/efi_loader/efi_var_file.c b/lib/efi_loader/efi_var_file.c
new file mode 100644
index 0000000000..6f9d76f2a2
--- /dev/null
+++ b/lib/efi_loader/efi_var_file.c
@@ -0,0 +1,233 @@
+// 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_status_t 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 0000000000..7a2dba7dc2
--- /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_var_seed.S b/lib/efi_loader/efi_var_seed.S
new file mode 100644
index 0000000000..e0a40cf46c
--- /dev/null
+++ b/lib/efi_loader/efi_var_seed.S
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Predefined UEFI variables
+ *
+ * Copyright (c) 2020, Heinrich Schuchardt <xypron.glpk@gmx.de>
+ */
+
+#include <config.h>
+
+.section .rodata.efi_seed.init,"a"
+.balign 16
+.global __efi_var_file_begin
+__efi_var_file_begin:
+.incbin CONFIG_EFI_VAR_SEED_FILE
+.global __efi_var_file_end
+__efi_var_file_end:
+.balign 16
diff --git a/lib/efi_loader/efi_variable.c b/lib/efi_loader/efi_variable.c
index efaba869ef..39a8482903 100644
--- a/lib/efi_loader/efi_variable.c
+++ b/lib/efi_loader/efi_variable.c
@@ -5,349 +5,23 @@
* Copyright (c) 2017 Rob Clark
*/
+#define LOG_CATEGORY LOGC_EFI
+
#include <common.h>
#include <efi_loader.h>
+#include <efi_variable.h>
#include <env.h>
#include <env_internal.h>
#include <hexdump.h>
+#include <log.h>
#include <malloc.h>
#include <rtc.h>
#include <search.h>
#include <uuid.h>
#include <crypto/pkcs7_parser.h>
-#include <linux/bitops.h>
#include <linux/compat.h>
#include <u-boot/crc.h>
-
-enum efi_secure_mode {
- EFI_MODE_SETUP,
- EFI_MODE_USER,
- EFI_MODE_AUDIT,
- EFI_MODE_DEPLOYED,
-};
-
-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
- * @setup_mode: value of SetupMode
- * @audit_mode: value of AuditMode
- * @deployed_mode: value of DeployedMode
- *
- * Modify secure boot status related variables as indicated.
- *
- * Return: status code
- */
-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;
-
- 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);
- if (ret != EFI_SUCCESS)
- goto err;
-
- ret = efi_set_variable_common(L"SetupMode", &efi_global_variable_guid,
- attributes, 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);
- if (ret != EFI_SUCCESS)
- goto err;
-
- ret = efi_set_variable_common(L"DeployedMode",
- &efi_global_variable_guid, attributes,
- sizeof(deployed_mode), &deployed_mode,
- false);
-err:
- return ret;
-}
-
-/**
- * efi_transfer_secure_state - handle a secure boot state transition
- * @mode: new state
- *
- * Depending on @mode, secure boot related variables are updated.
- * Those variables are *read-only* for users, efi_set_variable_common()
- * is called here.
- *
- * Return: status code
- */
-static efi_status_t efi_transfer_secure_state(enum efi_secure_mode mode)
-{
- efi_status_t ret;
-
- EFI_PRINT("Switching secure state from %d to %d\n", efi_secure_mode,
- mode);
-
- if (mode == EFI_MODE_DEPLOYED) {
- 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);
- 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)
- goto err;
- } else {
- return EFI_INVALID_PARAMETER;
- }
-
- efi_secure_mode = mode;
-
- return EFI_SUCCESS;
-
-err:
- /* TODO: What action should be taken here? */
- printf("ERROR: Secure state transition failed\n");
- return ret;
-}
-
-/**
- * efi_init_secure_state - initialize secure boot state
- *
- * Return: status code
- */
-static efi_status_t efi_init_secure_state(void)
-{
- enum efi_secure_mode mode;
- efi_uintn_t size;
- 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);
- 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);
-
-err:
- return ret;
-}
-
-/**
- * efi_secure_boot_enabled - return if secure boot is enabled or not
- *
- * Return: true if enabled, false if disabled
- */
-bool efi_secure_boot_enabled(void)
-{
- return efi_secure_boot;
-}
+#include <asm/sections.h>
#ifdef CONFIG_EFI_SECURE_BOOT
static u8 pkcs7_hdr[] = {
@@ -462,6 +136,7 @@ static efi_status_t efi_variable_authenticate(u16 *variable,
struct efi_time timestamp;
struct rtc_time tm;
u64 new_time;
+ enum efi_auth_var_type var_type;
efi_status_t ret;
var_sig = NULL;
@@ -538,18 +213,20 @@ static efi_status_t efi_variable_authenticate(u16 *variable,
}
/* signature database used for authentication */
- if (u16_strcmp(variable, L"PK") == 0 ||
- u16_strcmp(variable, L"KEK") == 0) {
+ var_type = efi_auth_var_get_type(variable, vendor);
+ switch (var_type) {
+ case EFI_AUTH_VAR_PK:
+ case EFI_AUTH_VAR_KEK:
/* with PK */
truststore = efi_sigstore_parse_sigdb(L"PK");
if (!truststore)
goto err;
- } else if (u16_strcmp(variable, L"db") == 0 ||
- u16_strcmp(variable, L"dbx") == 0) {
+ break;
+ case EFI_AUTH_VAR_DB:
+ case EFI_AUTH_VAR_DBX:
/* with PK and KEK */
truststore = efi_sigstore_parse_sigdb(L"KEK");
truststore2 = efi_sigstore_parse_sigdb(L"PK");
-
if (!truststore) {
if (!truststore2)
goto err;
@@ -557,7 +234,8 @@ static efi_status_t efi_variable_authenticate(u16 *variable,
truststore = truststore2;
truststore2 = NULL;
}
- } else {
+ break;
+ default:
/* TODO: support private authenticated variables */
goto err;
}
@@ -599,378 +277,148 @@ 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;
- }
+ *timep = var->time;
- 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;
- }
-
- 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);
- return EFI_SUCCESS;
-}
+ efi_var_mem_find(vendor, variable_name, &var);
-/**
- * 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;
+ enum efi_auth_var_type var_type;
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;
+ var_type = efi_auth_var_get_type(variable_name, vendor);
+ if (var) {
+ if (ro_check && (var->attr & EFI_VARIABLE_READ_ONLY))
+ return EFI_WRITE_PROTECTED;
+
+ if (IS_ENABLED(CONFIG_EFI_VARIABLES_PRESEED)) {
+ if (var_type != EFI_AUTH_VAR_NONE)
+ 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") ||
- !u16_strcmp(variable_name, L"KEK")) &&
- !guidcmp(vendor, &efi_global_variable_guid)) ||
- ((!u16_strcmp(variable_name, L"db") ||
- !u16_strcmp(variable_name, L"dbx")) &&
- !guidcmp(vendor, &efi_guid_image_security_database))) {
+ if (var_type != EFI_AUTH_VAR_NONE) {
/* 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 +429,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;
- }
-
- 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, ",");
+ ret = efi_var_mem_ins(variable_name, vendor, attributes,
+ data_size, data, 0, NULL, time);
}
- 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);
+ efi_var_mem_del(var);
-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 (var_type == EFI_AUTH_VAR_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 +495,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 +518,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 +543,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 +570,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 +589,20 @@ 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;
+ if (IS_ENABLED(CONFIG_EFI_VARIABLES_PRESEED)) {
+ ret = efi_var_restore((struct efi_var_file *)
+ __efi_var_file_begin);
+ if (ret != EFI_SUCCESS)
+ log_err("Invalid EFI variable seed\n");
+ }
+
+ return efi_var_from_file();
}
diff --git a/lib/efi_loader/efi_variable_tee.c b/lib/efi_loader/efi_variable_tee.c
index cacc76e23d..c042348938 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,25 +244,92 @@ 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
+/*
+ * StMM can store internal attributes and properties for variables, i.e enabling
+ * R/O variables
*/
-efi_status_t EFIAPI efi_get_variable(u16 *name, const efi_guid_t *guid,
- u32 *attr, efi_uintn_t *data_size,
- void *data)
+static efi_status_t set_property_int(u16 *variable_name, efi_uintn_t name_size,
+ const efi_guid_t *vendor,
+ struct var_check_property *var_property)
+{
+ struct smm_variable_var_check_property *smm_property;
+ efi_uintn_t payload_size;
+ u8 *comm_buf = NULL;
+ efi_status_t ret;
+
+ payload_size = sizeof(*smm_property) + name_size;
+ if (payload_size > max_payload_size) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+ comm_buf = setup_mm_hdr((void **)&smm_property, payload_size,
+ SMM_VARIABLE_FUNCTION_VAR_CHECK_VARIABLE_PROPERTY_SET,
+ &ret);
+ if (!comm_buf)
+ goto out;
+
+ guidcpy(&smm_property->guid, vendor);
+ smm_property->name_size = name_size;
+ memcpy(&smm_property->property, var_property,
+ sizeof(smm_property->property));
+ memcpy(smm_property->name, variable_name, name_size);
+
+ ret = mm_communicate(comm_buf, payload_size);
+
+out:
+ free(comm_buf);
+ return ret;
+}
+
+static efi_status_t get_property_int(u16 *variable_name, efi_uintn_t name_size,
+ const efi_guid_t *vendor,
+ struct var_check_property *var_property)
+{
+ struct smm_variable_var_check_property *smm_property;
+ efi_uintn_t payload_size;
+ u8 *comm_buf = NULL;
+ efi_status_t ret;
+
+ memset(var_property, 0, sizeof(*var_property));
+ payload_size = sizeof(*smm_property) + name_size;
+ if (payload_size > max_payload_size) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+ comm_buf = setup_mm_hdr((void **)&smm_property, payload_size,
+ SMM_VARIABLE_FUNCTION_VAR_CHECK_VARIABLE_PROPERTY_GET,
+ &ret);
+ if (!comm_buf)
+ goto out;
+
+ guidcpy(&smm_property->guid, vendor);
+ smm_property->name_size = name_size;
+ memcpy(smm_property->name, variable_name, name_size);
+
+ ret = mm_communicate(comm_buf, payload_size);
+ /*
+ * Currently only R/O property is supported in StMM.
+ * Variables that are not set to R/O will not set the property in StMM
+ * and the call will return EFI_NOT_FOUND. We are setting the
+ * properties to 0x0 so checking against that is enough for the
+ * EFI_NOT_FOUND case.
+ */
+ if (ret == EFI_NOT_FOUND)
+ ret = EFI_SUCCESS;
+ if (ret != EFI_SUCCESS)
+ goto out;
+ memcpy(var_property, &smm_property->property, sizeof(*var_property));
+
+out:
+ free(comm_buf);
+ return ret;
+}
+
+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 var_check_property var_property;
struct smm_variable_access *var_acc;
efi_uintn_t payload_size;
efi_uintn_t name_size;
@@ -269,15 +337,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 +366,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 +381,16 @@ 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;
+ ret = get_property_int(variable_name, name_size, vendor, &var_property);
+ if (ret != EFI_SUCCESS)
+ goto out;
+
+ if (attributes) {
+ *attributes = var_acc->attr;
+ if (var_property.property & VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY)
+ *attributes |= EFI_VARIABLE_READ_ONLY;
+ }
+
if (data)
memcpy(data, (u8 *)var_acc->name + var_acc->name_size,
var_acc->data_size);
@@ -325,38 +399,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 +427,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,37 +470,22 @@ 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)
{
+ efi_status_t ret, alt_ret = EFI_SUCCESS;
+ struct var_check_property var_property;
struct smm_variable_access *var_acc;
efi_uintn_t payload_size;
efi_uintn_t name_size;
u8 *comm_buf = NULL;
- efi_status_t ret;
+ bool ro;
- 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;
}
@@ -452,68 +493,91 @@ efi_status_t EFIAPI efi_set_variable(u16 *name, const efi_guid_t *guid,
ret = EFI_INVALID_PARAMETER;
goto out;
}
-
/* 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;
goto out;
}
- /* Get communication buffer and initialize header */
+ /*
+ * Allocate the buffer early, before switching to RW (if needed)
+ * so we won't need to account for any failures in reading/setting
+ * the properties, if the allocation fails
+ */
comm_buf = setup_mm_hdr((void **)&var_acc, payload_size,
SMM_VARIABLE_FUNCTION_SET_VARIABLE, &ret);
if (!comm_buf)
goto out;
+ ro = !!(attributes & EFI_VARIABLE_READ_ONLY);
+ attributes &= EFI_VARIABLE_MASK;
+
+ /*
+ * The API has the ability to override RO flags. If no RO check was
+ * requested switch the variable to RW for the duration of this call
+ */
+ ret = get_property_int(variable_name, name_size, vendor,
+ &var_property);
+ if (ret != EFI_SUCCESS)
+ goto out;
+
+ if (var_property.property & VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY) {
+ /* Bypass r/o check */
+ if (!ro_check) {
+ var_property.property &= ~VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY;
+ ret = set_property_int(variable_name, name_size, vendor, &var_property);
+ if (ret != EFI_SUCCESS)
+ goto out;
+ } else {
+ ret = EFI_WRITE_PROTECTED;
+ 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 */
ret = mm_communicate(comm_buf, payload_size);
+ if (ret != EFI_SUCCESS)
+ alt_ret = ret;
+
+ if (ro && !(var_property.property & VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY)) {
+ var_property.revision = VAR_CHECK_VARIABLE_PROPERTY_REVISION;
+ var_property.property |= VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY;
+ var_property.attributes = attributes;
+ var_property.minsize = 1;
+ var_property.maxsize = var_acc->data_size;
+ ret = set_property_int(variable_name, name_size, vendor, &var_property);
+ }
+ if (alt_ret != EFI_SUCCESS)
+ goto out;
+
+ if (!u16_strcmp(variable_name, L"PK"))
+ alt_ret = efi_init_secure_state();
out:
free(comm_buf);
- return EFI_EXIT(ret);
+ return alt_ret == EFI_SUCCESS ? ret : alt_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 +596,7 @@ efi_query_variable_info(u32 attributes, u64 *max_variable_storage_size,
out:
free(comm_buf);
- return EFI_EXIT(ret);
+ return ret;
}
/**
@@ -658,5 +722,9 @@ efi_status_t efi_init_variables(void)
MM_VARIABLE_COMMUNICATE_SIZE +
max_payload_size;
+ ret = efi_init_secure_state();
+ if (ret != EFI_SUCCESS)
+ return ret;
+
return EFI_SUCCESS;
}
diff --git a/lib/efi_selftest/efi_selftest_variables_runtime.c b/lib/efi_selftest/efi_selftest_variables_runtime.c
index b3b40ad2cf..3226069c0b 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 6c4bbc4625..2057f6819d 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 ca40b9beb0..e3bebe94c4 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_loader.py b/test/py/tests/test_efi_loader.py
index 9465c28fbc..7aa422e764 100644
--- a/test/py/tests/test_efi_loader.py
+++ b/test/py/tests/test_efi_loader.py
@@ -68,8 +68,8 @@ def test_efi_pre_commands(u_boot_console):
u_boot_console.run_command('pci enum')
@pytest.mark.buildconfigspec('cmd_dhcp')
-def test_efi_dhcp(u_boot_console):
- """Test the dhcp command.
+def test_efi_setup_dhcp(u_boot_console):
+ """Set up the network using DHCP.
The boardenv_* file may be used to enable/disable this test; see the
comment at the beginning of this file.
@@ -77,7 +77,10 @@ def test_efi_dhcp(u_boot_console):
test_dhcp = u_boot_console.config.env.get('env__net_dhcp_server', False)
if not test_dhcp:
- pytest.skip('No DHCP server available')
+ env_vars = u_boot_console.config.env.get('env__net_static_env_vars', None)
+ if not env_vars:
+ pytest.skip('No DHCP server available')
+ return None
u_boot_console.run_command('setenv autoload no')
output = u_boot_console.run_command('dhcp')
@@ -88,7 +91,7 @@ def test_efi_dhcp(u_boot_console):
@pytest.mark.buildconfigspec('net')
def test_efi_setup_static(u_boot_console):
- """Set up a static IP configuration.
+ """Set up the network using a static IP configuration.
The configuration is provided by the boardenv_* file; see the comment at
the beginning of this file.
@@ -96,7 +99,10 @@ def test_efi_setup_static(u_boot_console):
env_vars = u_boot_console.config.env.get('env__net_static_env_vars', None)
if not env_vars:
- pytest.skip('No static network configuration is defined')
+ test_dhcp = u_boot_console.config.env.get('env__net_dhcp_server', False)
+ if not test_dhcp:
+ pytest.skip('No static network configuration is defined')
+ return None
for (var, val) in env_vars:
u_boot_console.run_command('setenv %s %s' % (var, val))
diff --git a/test/py/tests/test_efi_secboot/conftest.py b/test/py/tests/test_efi_secboot/conftest.py
index ac5a780fdb..c6709700a8 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 d6222809c5..ba6b9f391e 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 148aa3123e..d0c6b9035b 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 19d78b1b64..7531bbac6a 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 c42c5ddc47..c4c3f4c202 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)