diff --git a/rk33xx-enable-make-itb.patch b/rk33xx-enable-make-itb.patch index c95b039..072af72 100644 --- a/rk33xx-enable-make-itb.patch +++ b/rk33xx-enable-make-itb.patch @@ -1,7 +1,7 @@ -From 5245a38260ff414e054d2f987907710f46e5a2e0 Mon Sep 17 00:00:00 2001 +From e1f184f835291f46220d1fb6c0e54d62822803c0 Mon Sep 17 00:00:00 2001 From: Peter Robinson -Date: Sun, 25 Feb 2018 19:15:39 +0000 -Subject: [PATCH] config: evb-rk3399: enable make itb +Date: Wed, 25 Apr 2018 10:48:19 +0100 +Subject: [PATCH 2/2] config: evb-rk3399: enable make uboot.itb Similar to firefly 3399 enable the ability to create a FIT image with combined arm-trusted-firmware. @@ -12,22 +12,26 @@ Signed-off-by: Peter Robinson 1 file changed, 3 insertions(+) diff --git a/configs/evb-rk3399_defconfig b/configs/evb-rk3399_defconfig -index b5ae073224..bf81b2f93a 100644 +index b36f232dcb..67ba0ce015 100644 --- a/configs/evb-rk3399_defconfig +++ b/configs/evb-rk3399_defconfig -@@ -11,9 +11,12 @@ CONFIG_DEFAULT_DEVICE_TREE="rk3399-evb" +@@ -11,6 +11,7 @@ CONFIG_DEFAULT_DEVICE_TREE="rk3399-evb" CONFIG_DEBUG_UART=y CONFIG_FIT=y CONFIG_SPL_LOAD_FIT=y +CONFIG_SPL_FIT_GENERATOR="arch/arm/mach-rockchip/make_fit_atf.py" # CONFIG_DISPLAY_CPUINFO is not set + CONFIG_DISPLAY_BOARDINFO_LATE=y CONFIG_SPL_STACK_R=y - CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN=0x4000 +@@ -25,6 +26,8 @@ CONFIG_CMD_TIME=y + CONFIG_SPL_OF_CONTROL=y + CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents" + CONFIG_SPL_OF_PLATDATA=y +CONFIG_SPL_ATF=y +CONFIG_SPL_ATF_NO_PLATFORM_PARAM=y - CONFIG_CMD_BOOTZ=y - CONFIG_CMD_GPT=y - CONFIG_CMD_MMC=y + CONFIG_ENV_IS_IN_MMC=y + CONFIG_NET_RANDOM_ETHADDR=y + CONFIG_REGMAP=y -- -2.14.3 +2.17.0 diff --git a/rk33xx-make_fit_atf-fix.patch b/rk33xx-make_fit_atf-fix.patch index ee54bb2..5407843 100644 --- a/rk33xx-make_fit_atf-fix.patch +++ b/rk33xx-make_fit_atf-fix.patch @@ -1,4 +1,4 @@ -From 319f90eb72054efc5022cc2183496fd7801a4e1e Mon Sep 17 00:00:00 2001 +From 72ba581632c53ad16d1b7174ac507fb7b0ee47c1 Mon Sep 17 00:00:00 2001 From: Patrick Uiterwijk Date: Wed, 14 Feb 2018 01:29:42 +0100 Subject: [PATCH 1/2] arm: rockchip: make_fit_atf: remove unneeded imports @@ -25,4 +25,5 @@ index 7c6dd57678..9a404d1d32 100755 ELF_SEG_P_TYPE='p_type' ELF_SEG_P_PADDR='p_paddr' -- -2.14.3 +2.17.0 + diff --git a/rockchip-make_fit_atf-fix-warning-unit_address_vs_reg.patch b/rockchip-make_fit_atf-fix-warning-unit_address_vs_reg.patch new file mode 100644 index 0000000..d64cbb1 --- /dev/null +++ b/rockchip-make_fit_atf-fix-warning-unit_address_vs_reg.patch @@ -0,0 +1,103 @@ +From patchwork Thu Apr 26 06:43:06 2018 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [U-Boot] rockchip: make_fit_atf: fix warning unit_address_vs_reg +X-Patchwork-Submitter: Kever Yang +X-Patchwork-Id: 904884 +Message-Id: <1524724986-28497-1-git-send-email-kever.yang@rock-chips.com> +To: u-boot@lists.denx.de +Date: Thu, 26 Apr 2018 14:43:06 +0800 +From: Kever Yang +List-Id: U-Boot discussion + +Patch fix warning: +/builddir/BUILD/u-boot-2018.05-rc2/"arch/arm/mach-rockchip/make_fit_atf.py" \ +arch/arm/dts/rk3399-firefly.dtb > u-boot.its + ./tools/mkimage -f u-boot.its -E u-boot.itb >/dev/null && cat +/dev/null +u-boot.itb.tmp: Warning (unit_address_vs_reg): Node /images/uboot@1 +has a unit name, but no reg property +u-boot.itb.tmp: Warning (unit_address_vs_reg): Node /images/atf@1 has +a unit name, but no reg property +u-boot.itb.tmp: Warning (unit_address_vs_reg): Node /images/atf@2 has +a unit name, but no reg property +u-boot.itb.tmp: Warning (unit_address_vs_reg): Node /images/atf@3 has +a unit name, but no reg property +u-boot.itb.tmp: Warning (unit_address_vs_reg): Node /images/fdt@1 has +a unit name, but no reg property +u-boot.itb.tmp: Warning (unit_address_vs_reg): Node +/configurations/config@1 has a unit name, but no reg property +make[1]: Leaving directory +'/builddir/BUILD/u-boot-2018.05-rc2/builds/firefly-rk3399' + +Reported-by: Peter Robinson +Signed-off-by: Kever Yang +--- + + arch/arm/mach-rockchip/make_fit_atf.py | 18 +++++++++--------- + 1 file changed, 9 insertions(+), 9 deletions(-) + +diff --git a/arch/arm/mach-rockchip/make_fit_atf.py b/arch/arm/mach-rockchip/make_fit_atf.py +index 7c6dd57..513e088 100755 +--- a/arch/arm/mach-rockchip/make_fit_atf.py ++++ b/arch/arm/mach-rockchip/make_fit_atf.py +@@ -37,7 +37,7 @@ DT_HEADER="""/* + #address-cells = <1>; + + images { +- uboot@1 { ++ uboot { + description = "U-Boot (64-bit)"; + data = /incbin/("u-boot-nodtb.bin"); + type = "standalone"; +@@ -61,7 +61,7 @@ def append_atf_node(file, atf_index, phy_addr): + Append ATF DT node to input FIT dts file. + """ + data = 'bl31_0x%08x.bin' % phy_addr +- print >> file, '\t\tatf@%d {' % atf_index ++ print >> file, '\t\tatf_%d {' % atf_index + print >> file, '\t\t\tdescription = \"ARM Trusted Firmware\";' + print >> file, '\t\t\tdata = /incbin/("%s");' % data + print >> file, '\t\t\ttype = "firmware";' +@@ -81,7 +81,7 @@ def append_fdt_node(file, dtbs): + cnt = 1 + for dtb in dtbs: + dtname = os.path.basename(dtb) +- print >> file, '\t\tfdt@%d {' % cnt ++ print >> file, '\t\tfdt_%d {' % cnt + print >> file, '\t\t\tdescription = "%s";' % dtname + print >> file, '\t\t\tdata = /incbin/("%s");' % dtb + print >> file, '\t\t\ttype = "flat_dt";' +@@ -91,17 +91,17 @@ def append_fdt_node(file, dtbs): + cnt = cnt + 1 + + def append_conf_section(file, cnt, dtname, atf_cnt): +- print >> file, '\t\tconfig@%d {' % cnt ++ print >> file, '\t\tconfig_%d {' % cnt + print >> file, '\t\t\tdescription = "%s";' % dtname +- print >> file, '\t\t\tfirmware = "atf@1";' +- print >> file, '\t\t\tloadables = "uboot@1",', ++ print >> file, '\t\t\tfirmware = "atf_1";' ++ print >> file, '\t\t\tloadables = "uboot",', + for i in range(1, atf_cnt): +- print >> file, '"atf@%d"' % (i+1), ++ print >> file, '"atf_%d"' % (i+1), + if i != (atf_cnt - 1): + print >> file, ',', + else: + print >> file, ';' +- print >> file, '\t\t\tfdt = "fdt@1";' ++ print >> file, '\t\t\tfdt = "fdt_1";' + print >> file, '\t\t};' + print >> file, '' + +@@ -111,7 +111,7 @@ def append_conf_node(file, dtbs, atf_cnt): + """ + cnt = 1 + print >> file, '\tconfigurations {' +- print >> file, '\t\tdefault = "config@1";' ++ print >> file, '\t\tdefault = "config_1";' + for dtb in dtbs: + dtname = os.path.basename(dtb) + append_conf_section(file, cnt, dtname, atf_cnt) diff --git a/tegra186-jetson-tx2-disable-onboard-emmc.patch b/tegra186-jetson-tx2-disable-onboard-emmc.patch new file mode 100644 index 0000000..ebdb31a --- /dev/null +++ b/tegra186-jetson-tx2-disable-onboard-emmc.patch @@ -0,0 +1,26 @@ +From dbe4dff86520a1373076563d1bee5ada1d7fd7c5 Mon Sep 17 00:00:00 2001 +From: Peter Robinson +Date: Thu, 26 Apr 2018 16:56:54 +0100 +Subject: [PATCH] tegra186: jetson-tx2: disable onboard emmc + +Signed-off-by: Peter Robinson +--- + arch/arm/dts/tegra186-p2771-0000.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm/dts/tegra186-p2771-0000.dtsi b/arch/arm/dts/tegra186-p2771-0000.dtsi +index a1319dc493..e220f086ee 100644 +--- a/arch/arm/dts/tegra186-p2771-0000.dtsi ++++ b/arch/arm/dts/tegra186-p2771-0000.dtsi +@@ -53,7 +53,7 @@ + }; + + sdhci@3460000 { +- status = "okay"; ++ status = "disabled"; + bus-width = <8>; + non-removable; + }; +-- +2.17.0 + diff --git a/uboot-tools.spec b/uboot-tools.spec index 81ed121..62f31cd 100644 --- a/uboot-tools.spec +++ b/uboot-tools.spec @@ -2,7 +2,7 @@ Name: uboot-tools Version: 2018.05 -Release: 0.2%{?candidate:.%{candidate}}%{?dist} +Release: 0.3%{?candidate:.%{candidate}}%{?dist} Summary: U-Boot utilities License: GPLv2+ BSD LGPL-2.1+ LGPL-2.0+ URL: http://www.denx.de/wiki/U-Boot @@ -20,15 +20,18 @@ Patch1: uefi-use-Fedora-specific-path-name.patch # general fixes Patch2: uefi-distro-load-FDT-from-any-partition-on-boot-device.patch Patch3: usb-kbd-fixes.patch -Patch4: rk33xx-make_fit_atf-fix.patch -#Patch5: rk33xx-enable-make-itb.patch +Patch4: uefi-upstream-test.patch # Board fixes and enablement -Patch10: dragonboard-fixes.patch -Patch12: mx6cuboxi-add-support-for-detecting-Revision-1.5-SoM.patch -Patch13: rpi-Enable-using-the-DT-provided-by-the-Raspberry-Pi.patch -Patch19: mmc-mv_sdhci-zero-out-sdhci_host-structure.patch -Patch21: sunxi-improve-throughput-in-the-sunxi_mmc-driver.patch +Patch11: mx6cuboxi-add-support-for-detecting-Revision-1.5-SoM.patch +Patch12: dragonboard-fixes.patch +#Patch13: pi-Enable-using-the-DT-provided-by-the-Raspberry-Pi.patch +Patch14: rk33xx-make_fit_atf-fix.patch +Patch15: rk33xx-enable-make-itb.patch +Patch16: rockchip-make_fit_atf-fix-warning-unit_address_vs_reg.patch +Patch17: mmc-mv_sdhci-zero-out-sdhci_host-structure.patch +Patch18: sunxi-improve-throughput-in-the-sunxi_mmc-driver.patch +Patch19: tegra186-jetson-tx2-disable-onboard-emmc.patch # Patch99: mvebu-enable-generic-distro-boot-config.patch @@ -130,6 +133,8 @@ do if [[ " ${rk33xx[*]} " == *" $board "* ]]; then echo "Board: $board using rk33xx" make HOSTCC="gcc $RPM_OPT_FLAGS" CROSS_COMPILE="" u-boot.itb V=1 O=builds/$(echo $board)/ + builds/$(echo $board)/tools/mkimage -n rk3399 -T rksd -d builds/$(echo $board)/spl/u-boot-spl.bin builds/$(echo $board)/spl_sd.img + builds/$(echo $board)/tools/mkimage -n rk3399 -T rkspi -d builds/$(echo $board)/spl/u-boot-spl.bin builds/$(echo $board)/spl_spi.img fi done @@ -192,7 +197,7 @@ done for board in $(cat %{_arch}-boards) do mkdir -p $RPM_BUILD_ROOT%{_datadir}/uboot/$(echo $board)/ - for file in MLO SPL spl/arndale-spl.bin spl/origen-spl.bin spl/smdkv310-spl.bin u-boot.bin u-boot.dtb u-boot-dtb-tegra.bin u-boot.img u-boot.imx u-boot-nodtb-tegra.bin u-boot-spl.kwb u-boot-sunxi-with-spl.bin + for file in MLO SPL spl/arndale-spl.bin spl/origen-spl.bin spl/smdkv310-spl.bin u-boot.bin u-boot.dtb u-boot-dtb-tegra.bin u-boot.img u-boot.imx u-boot-nodtb-tegra.bin u-boot-spl.kwb u-boot-sunxi-with-spl.bin spl_sd.img spl_spi.img do if [ -f builds/$(echo $board)/$(echo $file) ]; then install -p -m 0644 builds/$(echo $board)/$(echo $file) $RPM_BUILD_ROOT%{_datadir}/uboot/$(echo $board)/ @@ -289,6 +294,11 @@ cp -p board/warp7/README builds/docs/README.warp7 %endif %changelog +* Thu Apr 26 2018 Peter Robinson 2018.05-0.3-rc2 +- uEFI improvements +- Fixes for Rockchips rk33xx 64 bit devices +- Build AllWinner 64 bit devices against new ATF + * Tue Apr 17 2018 Peter Robinson 2018.05-0.2-rc2 - 2018.05 RC2 - Enable Raspberry Pi option to use firmware DT diff --git a/uefi-upstream-test.patch b/uefi-upstream-test.patch new file mode 100644 index 0000000..f658b6c --- /dev/null +++ b/uefi-upstream-test.patch @@ -0,0 +1,1233 @@ +From d8d8997bbce7ff81799cb20795bdf97db9f8d5f2 Mon Sep 17 00:00:00 2001 +From: Heinrich Schuchardt +Date: Fri, 23 Mar 2018 21:12:17 +0100 +Subject: [PATCH 01/10] log: fix typo LOGL_EFI + +According to the documentation the EFI log category is called LOGC_EFI. +All other categories start with LOGC_. So let's fix it. + +Fixes: 1973b381a1b3 ("log: add category LOGC_EFI") +Signed-off-by: Heinrich Schuchardt +Reviewed-by: Simon Glass +Signed-off-by: Alexander Graf +--- + include/log.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/include/log.h b/include/log.h +index 20dc5289c7..3cf08de6d0 100644 +--- a/include/log.h ++++ b/include/log.h +@@ -46,7 +46,7 @@ enum log_category_t { + LOGC_CORE, + LOGC_DM, /* Core driver-model */ + LOGC_DT, /* Device-tree */ +- LOGL_EFI, /* EFI implementation */ ++ LOGC_EFI, /* EFI implementation */ + + LOGC_COUNT, + LOGC_END, +-- +2.17.0 + +From 26ed7144848503cf7b4812c751462bc6949bcaa6 Mon Sep 17 00:00:00 2001 +From: Peter Robinson +Date: Wed, 18 Apr 2018 13:02:45 +0100 +Subject: [PATCH] sunxi: A64/H5 devices: enable usb keyboard support + +Now the A64/H5 SoCs support video output it's useful to enable usb keyboard +support so console can be used via standard keyboard/video interface. + +Tested on Pine64. + +Signed-off-by: Peter Robinson +--- + configs/a64-olinuxino_defconfig | 2 ++ + configs/bananapi_m64_defconfig | 2 ++ + configs/nanopi_a64_defconfig | 2 ++ + configs/orangepi_pc2_defconfig | 2 ++ + configs/orangepi_win_defconfig | 2 ++ + configs/orangepi_zero_plus2_defconfig | 2 ++ + configs/pine64_plus_defconfig | 2 ++ + configs/sopine_baseboard_defconfig | 2 ++ + 8 files changed, 16 insertions(+) + +diff --git a/configs/a64-olinuxino_defconfig b/configs/a64-olinuxino_defconfig +index b32df990a0..b0e23fc630 100644 +--- a/configs/a64-olinuxino_defconfig ++++ b/configs/a64-olinuxino_defconfig +@@ -12,3 +12,5 @@ CONFIG_DEFAULT_DEVICE_TREE="sun50i-a64-olinuxino" + CONFIG_SUN8I_EMAC=y + CONFIG_USB_EHCI_HCD=y + CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y ++CONFIG_DM_KEYBOARD=y ++CONFIG_USB_KEYBOARD=y +diff --git a/configs/bananapi_m64_defconfig b/configs/bananapi_m64_defconfig +index 47f31c6d9d..c2997223ab 100644 +--- a/configs/bananapi_m64_defconfig ++++ b/configs/bananapi_m64_defconfig +@@ -13,3 +13,5 @@ CONFIG_DEFAULT_DEVICE_TREE="sun50i-a64-bananapi-m64" + CONFIG_SUN8I_EMAC=y + CONFIG_USB_EHCI_HCD=y + CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y ++CONFIG_DM_KEYBOARD=y ++CONFIG_USB_KEYBOARD=y +diff --git a/configs/nanopi_a64_defconfig b/configs/nanopi_a64_defconfig +index 0a04911c81..458fcc6f8e 100644 +--- a/configs/nanopi_a64_defconfig ++++ b/configs/nanopi_a64_defconfig +@@ -11,3 +11,5 @@ CONFIG_DEFAULT_DEVICE_TREE="sun50i-a64-nanopi-a64" + CONFIG_SUN8I_EMAC=y + CONFIG_USB_EHCI_HCD=y + CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y ++CONFIG_DM_KEYBOARD=y ++CONFIG_USB_KEYBOARD=y +diff --git a/configs/orangepi_pc2_defconfig b/configs/orangepi_pc2_defconfig +index dd5f2c78ab..f89b67894d 100644 +--- a/configs/orangepi_pc2_defconfig ++++ b/configs/orangepi_pc2_defconfig +@@ -14,3 +14,5 @@ CONFIG_DEFAULT_DEVICE_TREE="sun50i-h5-orangepi-pc2" + CONFIG_SUN8I_EMAC=y + CONFIG_USB_EHCI_HCD=y + CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y ++CONFIG_DM_KEYBOARD=y ++CONFIG_USB_KEYBOARD=y +diff --git a/configs/orangepi_win_defconfig b/configs/orangepi_win_defconfig +index d7211b5823..de014a2766 100644 +--- a/configs/orangepi_win_defconfig ++++ b/configs/orangepi_win_defconfig +@@ -12,3 +12,5 @@ CONFIG_DEFAULT_DEVICE_TREE="sun50i-a64-orangepi-win" + CONFIG_SUN8I_EMAC=y + CONFIG_USB_EHCI_HCD=y + CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y ++CONFIG_DM_KEYBOARD=y ++CONFIG_USB_KEYBOARD=y +diff --git a/configs/orangepi_zero_plus2_defconfig b/configs/orangepi_zero_plus2_defconfig +index fdb6bb4ed9..fb5f1b2388 100644 +--- a/configs/orangepi_zero_plus2_defconfig ++++ b/configs/orangepi_zero_plus2_defconfig +@@ -14,3 +14,5 @@ CONFIG_DEFAULT_DEVICE_TREE="sun50i-h5-orangepi-zero-plus2" + CONFIG_SUN8I_EMAC=y + CONFIG_USB_EHCI_HCD=y + CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y ++CONFIG_DM_KEYBOARD=y ++CONFIG_USB_KEYBOARD=y +diff --git a/configs/pine64_plus_defconfig b/configs/pine64_plus_defconfig +index 21ce06f370..b4dbc7d03e 100644 +--- a/configs/pine64_plus_defconfig ++++ b/configs/pine64_plus_defconfig +@@ -14,3 +14,5 @@ CONFIG_RTL8211E_PINE64_GIGABIT_FIX=y + CONFIG_SUN8I_EMAC=y + CONFIG_USB_EHCI_HCD=y + CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y ++CONFIG_DM_KEYBOARD=y ++CONFIG_USB_KEYBOARD=y +diff --git a/configs/sopine_baseboard_defconfig b/configs/sopine_baseboard_defconfig +index 05436a1b43..a7db99d1e2 100644 +--- a/configs/sopine_baseboard_defconfig ++++ b/configs/sopine_baseboard_defconfig +@@ -18,3 +18,5 @@ CONFIG_DEFAULT_DEVICE_TREE="sun50i-a64-pine64-plus" + CONFIG_SUN8I_EMAC=y + CONFIG_USB_EHCI_HCD=y + CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y ++CONFIG_DM_KEYBOARD=y ++CONFIG_USB_KEYBOARD=y +-- +2.17.0 + +From c524997acb3d322e1bbd36c06ad02ef589705e7c Mon Sep 17 00:00:00 2001 +From: Heinrich Schuchardt +Date: Wed, 11 Apr 2018 00:41:52 +0200 +Subject: [PATCH 02/10] efi_loader: no support for ARMV7_NONSEC=y + +We do not support bootefi booting ARMv7 in non-secure mode. + +Signed-off-by: Heinrich Schuchardt +Signed-off-by: Alexander Graf +--- + doc/README.uefi | 2 ++ + lib/efi_loader/Kconfig | 2 ++ + 2 files changed, 4 insertions(+) + +diff --git a/doc/README.uefi b/doc/README.uefi +index 7403be3614..bb89b7ac2f 100644 +--- a/doc/README.uefi ++++ b/doc/README.uefi +@@ -324,6 +324,8 @@ This driver is only available if U-Boot is configured with + * persistence + * runtime support + ++* support bootefi booting ARMv7 in non-secure mode (CONFIG_ARMV7_NONSEC=y) ++ + ## Links + + * [1](http://uefi.org/specifications) +diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig +index 83d75c4fdc..d38780b604 100644 +--- a/lib/efi_loader/Kconfig ++++ b/lib/efi_loader/Kconfig +@@ -1,6 +1,8 @@ + config EFI_LOADER + bool "Support running EFI Applications in U-Boot" + depends on (ARM || X86) && OF_LIBFDT ++ # We do not support bootefi booting ARMv7 in non-secure mode ++ depends on !ARMV7_NONSEC + # We need EFI_STUB_64BIT to be set on x86_64 with EFI_STUB + depends on !EFI_STUB || !X86_64 || EFI_STUB_64BIT + # We need EFI_STUB_32BIT to be set on x86_32 with EFI_STUB +-- +2.17.0 + +From b5cd6878e43f913ae31c80425e410ca975082b4a Mon Sep 17 00:00:00 2001 +From: Heinrich Schuchardt +Date: Mon, 16 Apr 2018 07:59:03 +0200 +Subject: [PATCH 03/10] efi_selftest: do not execute test if setup failed + +Executing a test after failed setup may lead to unexpected behavior like +an illegal memory access. So after a setup failure we should skip to +teardown. + +Signed-off-by: Heinrich Schuchardt +Signed-off-by: Alexander Graf +--- + include/efi_selftest.h | 2 ++ + lib/efi_selftest/efi_selftest.c | 14 +++++++------- + 2 files changed, 9 insertions(+), 7 deletions(-) + +diff --git a/include/efi_selftest.h b/include/efi_selftest.h +index 08dd8e43ad..c23bc24bed 100644 +--- a/include/efi_selftest.h ++++ b/include/efi_selftest.h +@@ -114,6 +114,7 @@ u16 efi_st_get_key(void); + * @setup: set up the unit test + * @teardown: tear down the unit test + * @execute: execute the unit test ++ * @setup_ok: setup was successful (set at runtime) + * @on_request: test is only executed on request + */ + struct efi_unit_test { +@@ -123,6 +124,7 @@ struct efi_unit_test { + const struct efi_system_table *systable); + int (*execute)(void); + int (*teardown)(void); ++ int setup_ok; + bool on_request; + }; + +diff --git a/lib/efi_selftest/efi_selftest.c b/lib/efi_selftest/efi_selftest.c +index fc5ef254a1..fd4fee726f 100644 +--- a/lib/efi_selftest/efi_selftest.c ++++ b/lib/efi_selftest/efi_selftest.c +@@ -77,20 +77,20 @@ void efi_st_exit_boot_services(void) + */ + static int setup(struct efi_unit_test *test, unsigned int *failures) + { +- int ret; +- +- if (!test->setup) ++ if (!test->setup) { ++ test->setup_ok = EFI_ST_SUCCESS; + return EFI_ST_SUCCESS; ++ } + efi_st_printc(EFI_LIGHTBLUE, "\nSetting up '%s'\n", test->name); +- ret = test->setup(handle, systable); +- if (ret != EFI_ST_SUCCESS) { ++ test->setup_ok = test->setup(handle, systable); ++ if (test->setup_ok != EFI_ST_SUCCESS) { + efi_st_error("Setting up '%s' failed\n", test->name); + ++*failures; + } else { + efi_st_printc(EFI_LIGHTGREEN, + "Setting up '%s' succeeded\n", test->name); + } +- return ret; ++ return test->setup_ok; + } + + /* +@@ -200,7 +200,7 @@ void efi_st_do_tests(const u16 *testname, unsigned int phase, + continue; + if (steps & EFI_ST_SETUP) + setup(test, failures); +- if (steps & EFI_ST_EXECUTE) ++ if (steps & EFI_ST_EXECUTE && test->setup_ok == EFI_ST_SUCCESS) + execute(test, failures); + if (steps & EFI_ST_TEARDOWN) + teardown(test, failures); +-- +2.17.0 + +From 065a8eca69eaff1022717664ea516b1d9c7ca05d Mon Sep 17 00:00:00 2001 +From: Heinrich Schuchardt +Date: Mon, 16 Apr 2018 07:59:04 +0200 +Subject: [PATCH 04/10] efi_selftest: fix typo in efi_selftest_devicepath.c + +%s/provice/provide/ + +Signed-off-by: Heinrich Schuchardt +Signed-off-by: Alexander Graf +--- + lib/efi_selftest/efi_selftest_devicepath.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/lib/efi_selftest/efi_selftest_devicepath.c b/lib/efi_selftest/efi_selftest_devicepath.c +index 92940c7ab6..da68102eb2 100644 +--- a/lib/efi_selftest/efi_selftest_devicepath.c ++++ b/lib/efi_selftest/efi_selftest_devicepath.c +@@ -52,7 +52,7 @@ struct efi_device_path_to_text_protocol *device_path_to_text; + * Setup unit test. + * + * Create three handles. Install a new protocol on two of them and +- * provice device paths. ++ * provide device paths. + * + * handle1 + * guid interface +-- +2.17.0 + +From 211314c107d759c6adeb9b5dd8c81b284c4a03be Mon Sep 17 00:00:00 2001 +From: Heinrich Schuchardt +Date: Mon, 16 Apr 2018 07:59:05 +0200 +Subject: [PATCH 05/10] efi_loader: implement CreateDeviceNode + +Implement the CreateDeviceNode service of the device path utility protocol. + +Signed-off-by: Heinrich Schuchardt +Signed-off-by: Alexander Graf +--- + include/efi_loader.h | 5 ++++- + lib/efi_loader/efi_device_path.c | 15 +++++++++++++++ + lib/efi_loader/efi_device_path_utilities.c | 17 ++++++++++++++++- + 3 files changed, 35 insertions(+), 2 deletions(-) + +diff --git a/include/efi_loader.h b/include/efi_loader.h +index 17f9d3d1ef..0358bcb1d7 100644 +--- a/include/efi_loader.h ++++ b/include/efi_loader.h +@@ -330,7 +330,10 @@ struct efi_device_path *efi_dp_append(const struct efi_device_path *dp1, + const struct efi_device_path *dp2); + struct efi_device_path *efi_dp_append_node(const struct efi_device_path *dp, + const struct efi_device_path *node); +- ++/* Create a device path node of given type, sub-type, length */ ++struct efi_device_path *efi_dp_create_device_node(const u8 type, ++ const u8 sub_type, ++ const u16 length); + + struct efi_device_path *efi_dp_from_dev(struct udevice *dev); + struct efi_device_path *efi_dp_from_part(struct blk_desc *desc, int part); +diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c +index e965f1d88e..0cd0b459e3 100644 +--- a/lib/efi_loader/efi_device_path.c ++++ b/lib/efi_loader/efi_device_path.c +@@ -315,6 +315,21 @@ struct efi_device_path *efi_dp_append_node(const struct efi_device_path *dp, + return ret; + } + ++struct efi_device_path *efi_dp_create_device_node(const u8 type, ++ const u8 sub_type, ++ const u16 length) ++{ ++ struct efi_device_path *ret; ++ ++ ret = dp_alloc(length); ++ if (!ret) ++ return ret; ++ ret->type = type; ++ ret->sub_type = sub_type; ++ ret->length = length; ++ return ret; ++} ++ + #ifdef CONFIG_DM + /* size of device-path not including END node for device and all parents + * up to the root device. +diff --git a/lib/efi_loader/efi_device_path_utilities.c b/lib/efi_loader/efi_device_path_utilities.c +index bc97eeee31..e73188b242 100644 +--- a/lib/efi_loader/efi_device_path_utilities.c ++++ b/lib/efi_loader/efi_device_path_utilities.c +@@ -70,11 +70,26 @@ static bool EFIAPI is_device_path_multi_instance( + return EFI_EXIT(false); + } + ++/* ++ * Create device node. ++ * ++ * This function implements the CreateDeviceNode service of the device path ++ * utilities protocol. ++ * ++ * See the Unified Extensible Firmware Interface (UEFI) specification ++ * for details. ++ * ++ * @node_type node type ++ * @node_sub_type node sub type ++ * @node_length node length ++ * @return device path node ++ */ + static struct efi_device_path * EFIAPI create_device_node( + uint8_t node_type, uint8_t node_sub_type, uint16_t node_length) + { + EFI_ENTRY("%u, %u, %u", node_type, node_sub_type, node_length); +- return EFI_EXIT(NULL); ++ return EFI_EXIT(efi_dp_create_device_node(node_type, node_sub_type, ++ node_length)); + } + + const struct efi_device_path_utilities_protocol efi_device_path_utilities = { +-- +2.17.0 + +From 07836345ba6da5cdad2bbdc43923604d256645f3 Mon Sep 17 00:00:00 2001 +From: Heinrich Schuchardt +Date: Mon, 16 Apr 2018 07:59:06 +0200 +Subject: [PATCH 06/10] efi_loader: fix AppendDevicePath + +The logic of the AppendDevicePath service of the +EFI_DEVICE_PATH_UTILITIES_PROTOCOL is incorrectly implemented: + +* if both paths are NULL an end node has to be returned +* if both paths are not NULL the end node of the second device path has to + be kept + +Signed-off-by: Heinrich Schuchardt +Signed-off-by: Alexander Graf +--- + lib/efi_loader/efi_device_path.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c +index 0cd0b459e3..9b4d9ae0ab 100644 +--- a/lib/efi_loader/efi_device_path.c ++++ b/lib/efi_loader/efi_device_path.c +@@ -263,7 +263,10 @@ struct efi_device_path *efi_dp_append(const struct efi_device_path *dp1, + { + struct efi_device_path *ret; + +- if (!dp1) { ++ if (!dp1 && !dp2) { ++ /* return an end node */ ++ ret = efi_dp_dup(&END); ++ } else if (!dp1) { + ret = efi_dp_dup(dp2); + } else if (!dp2) { + ret = efi_dp_dup(dp1); +@@ -275,8 +278,8 @@ struct efi_device_path *efi_dp_append(const struct efi_device_path *dp1, + if (!p) + return NULL; + memcpy(p, dp1, sz1); +- memcpy(p + sz1, dp2, sz2); +- memcpy(p + sz1 + sz2, &END, sizeof(END)); ++ /* the end node of the second device path has to be retained */ ++ memcpy(p + sz1, dp2, sz2 + sizeof(END)); + ret = p; + } + +-- +2.17.0 + +From adb575124d717b57bb2abb9e63875cb23601c44b Mon Sep 17 00:00:00 2001 +From: Heinrich Schuchardt +Date: Mon, 16 Apr 2018 07:59:07 +0200 +Subject: [PATCH 07/10] efi_loader: correctly determine length of empty device + path + +efi_dp_size() is meant to return the device path length without the end +node. + +The length of a device path containing only an end node was incorrectly +reported as 4. + +Signed-off-by: Heinrich Schuchardt +Signed-off-by: Alexander Graf +--- + lib/efi_loader/efi_device_path.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c +index 9b4d9ae0ab..a2e48851d7 100644 +--- a/lib/efi_loader/efi_device_path.c ++++ b/lib/efi_loader/efi_device_path.c +@@ -234,6 +234,8 @@ unsigned efi_dp_size(const struct efi_device_path *dp) + { + unsigned sz = 0; + ++ if (!dp || dp->type == DEVICE_PATH_TYPE_END) ++ return 0; + while (dp) { + sz += dp->length; + dp = efi_dp_next(dp); +-- +2.17.0 + +From f6dd3f359c346da64f7db331b82086270388da0c Mon Sep 17 00:00:00 2001 +From: Heinrich Schuchardt +Date: Mon, 16 Apr 2018 07:59:08 +0200 +Subject: [PATCH 08/10] efi_loader: correcty determine total device path length + +Device paths may consist of multiple instances. Up to now we have only +considered the size of the first instance. For the services of the +EFI_DEVICE_PATH_UTILITIES_PROTOCOL in most cases the total length of the +device path is relevant. + +So let's rename efi_dp_size() to efi_dp_instance_size() and create a new +function efi_dp_size() that calculates the total device path length. + +Signed-off-by: Heinrich Schuchardt +Signed-off-by: Alexander Graf +--- + include/efi_loader.h | 5 ++++- + lib/efi_loader/efi_boottime.c | 4 ++-- + lib/efi_loader/efi_device_path.c | 34 +++++++++++++++++++++++--------- + 3 files changed, 31 insertions(+), 12 deletions(-) + +diff --git a/include/efi_loader.h b/include/efi_loader.h +index 0358bcb1d7..1298b5e160 100644 +--- a/include/efi_loader.h ++++ b/include/efi_loader.h +@@ -324,7 +324,10 @@ int efi_dp_match(const struct efi_device_path *a, + const struct efi_device_path *b); + struct efi_object *efi_dp_find_obj(struct efi_device_path *dp, + struct efi_device_path **rem); +-unsigned efi_dp_size(const struct efi_device_path *dp); ++/* get size of the first device path instance excluding end node */ ++efi_uintn_t efi_dp_instance_size(const struct efi_device_path *dp); ++/* size of multi-instance device path excluding end node */ ++efi_uintn_t efi_dp_size(const struct efi_device_path *dp); + struct efi_device_path *efi_dp_dup(const struct efi_device_path *dp); + struct efi_device_path *efi_dp_append(const struct efi_device_path *dp1, + const struct efi_device_path *dp2); +diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c +index 7a9449f59c..1cfdabf6eb 100644 +--- a/lib/efi_loader/efi_boottime.c ++++ b/lib/efi_loader/efi_boottime.c +@@ -2219,7 +2219,7 @@ static efi_status_t EFIAPI efi_locate_device_path( + } + + /* Find end of device path */ +- len = efi_dp_size(*device_path); ++ len = efi_dp_instance_size(*device_path); + + /* Get all handles implementing the protocol */ + ret = EFI_CALL(efi_locate_handle_buffer(BY_PROTOCOL, protocol, NULL, +@@ -2234,7 +2234,7 @@ static efi_status_t EFIAPI efi_locate_device_path( + if (ret != EFI_SUCCESS) + continue; + dp = (struct efi_device_path *)handler->protocol_interface; +- len_dp = efi_dp_size(dp); ++ len_dp = efi_dp_instance_size(dp); + /* + * This handle can only be a better fit + * if its device path length is longer than the best fit and +diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c +index a2e48851d7..ada0a9c268 100644 +--- a/lib/efi_loader/efi_device_path.c ++++ b/lib/efi_loader/efi_device_path.c +@@ -149,7 +149,7 @@ static struct efi_object *find_obj(struct efi_device_path *dp, bool short_path, + struct efi_device_path **rem) + { + struct efi_object *efiobj; +- unsigned int dp_size = efi_dp_size(dp); ++ efi_uintn_t dp_size = efi_dp_instance_size(dp); + + list_for_each_entry(efiobj, &efi_obj_list, link) { + struct efi_handler *handler; +@@ -170,11 +170,12 @@ static struct efi_object *find_obj(struct efi_device_path *dp, bool short_path, + * the caller. + */ + *rem = ((void *)dp) + +- efi_dp_size(obj_dp); ++ efi_dp_instance_size(obj_dp); + return efiobj; + } else { + /* Only return on exact matches */ +- if (efi_dp_size(obj_dp) == dp_size) ++ if (efi_dp_instance_size(obj_dp) == ++ dp_size) + return efiobj; + } + } +@@ -229,10 +230,10 @@ const struct efi_device_path *efi_dp_last_node(const struct efi_device_path *dp) + return ret; + } + +-/* return size not including End node: */ +-unsigned efi_dp_size(const struct efi_device_path *dp) ++/* get size of the first device path instance excluding end node */ ++efi_uintn_t efi_dp_instance_size(const struct efi_device_path *dp) + { +- unsigned sz = 0; ++ efi_uintn_t sz = 0; + + if (!dp || dp->type == DEVICE_PATH_TYPE_END) + return 0; +@@ -244,10 +245,25 @@ unsigned efi_dp_size(const struct efi_device_path *dp) + return sz; + } + ++/* get size of multi-instance device path excluding end node */ ++efi_uintn_t efi_dp_size(const struct efi_device_path *dp) ++{ ++ const struct efi_device_path *p = dp; ++ ++ if (!p) ++ return 0; ++ while (p->type != DEVICE_PATH_TYPE_END || ++ p->sub_type != DEVICE_PATH_SUB_TYPE_END) ++ p = (void *)p + p->length; ++ ++ return (void *)p - (void *)dp; ++} ++ ++/* copy multi-instance device path */ + struct efi_device_path *efi_dp_dup(const struct efi_device_path *dp) + { + struct efi_device_path *ndp; +- unsigned sz = efi_dp_size(dp) + sizeof(END); ++ size_t sz = efi_dp_size(dp) + sizeof(END); + + if (!dp) + return NULL; +@@ -298,7 +314,7 @@ struct efi_device_path *efi_dp_append_node(const struct efi_device_path *dp, + } else if (!node) { + ret = efi_dp_dup(dp); + } else if (!dp) { +- unsigned sz = node->length; ++ size_t sz = node->length; + void *p = dp_alloc(sz + sizeof(END)); + if (!p) + return NULL; +@@ -307,7 +323,7 @@ struct efi_device_path *efi_dp_append_node(const struct efi_device_path *dp, + ret = p; + } else { + /* both dp and node are non-null */ +- unsigned sz = efi_dp_size(dp); ++ size_t sz = efi_dp_size(dp); + void *p = dp_alloc(sz + node->length + sizeof(END)); + if (!p) + return NULL; +-- +2.17.0 + +From 3acef5da40f694af74f6165ffd47041231d9e6e1 Mon Sep 17 00:00:00 2001 +From: Heinrich Schuchardt +Date: Mon, 16 Apr 2018 07:59:09 +0200 +Subject: [PATCH 09/10] efi_loader: complete EFI_DEVICE_PATH_UTILITIES_PROTOCOL + +The missing services of the EFI_DEVICE_PATH_UTILITIES_PROTOCOL are +implemented. + +Signed-off-by: Heinrich Schuchardt +Signed-off-by: Alexander Graf +--- + include/efi_api.h | 1 + + include/efi_loader.h | 9 ++ + lib/efi_loader/efi_device_path.c | 64 ++++++++++++ + lib/efi_loader/efi_device_path_utilities.c | 116 +++++++++++++++++++-- + 4 files changed, 180 insertions(+), 10 deletions(-) + +diff --git a/include/efi_api.h b/include/efi_api.h +index ae93061160..64c27e494b 100644 +--- a/include/efi_api.h ++++ b/include/efi_api.h +@@ -343,6 +343,7 @@ struct efi_loaded_image { + 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b ) + + #define DEVICE_PATH_TYPE_END 0x7f ++# define DEVICE_PATH_SUB_TYPE_INSTANCE_END 0x01 + # define DEVICE_PATH_SUB_TYPE_END 0xff + + struct efi_device_path { +diff --git a/include/efi_loader.h b/include/efi_loader.h +index 1298b5e160..8d21ba74b1 100644 +--- a/include/efi_loader.h ++++ b/include/efi_loader.h +@@ -337,6 +337,15 @@ struct efi_device_path *efi_dp_append_node(const struct efi_device_path *dp, + struct efi_device_path *efi_dp_create_device_node(const u8 type, + const u8 sub_type, + const u16 length); ++/* Append device path instance */ ++struct efi_device_path *efi_dp_append_instance( ++ const struct efi_device_path *dp, ++ const struct efi_device_path *dpi); ++/* Get next device path instance */ ++struct efi_device_path *efi_dp_get_next_instance(struct efi_device_path **dp, ++ efi_uintn_t *size); ++/* Check if a device path contains muliple instances */ ++bool efi_dp_is_multi_instance(const struct efi_device_path *dp); + + struct efi_device_path *efi_dp_from_dev(struct udevice *dev); + struct efi_device_path *efi_dp_from_part(struct blk_desc *desc, int part); +diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c +index ada0a9c268..634dacf41b 100644 +--- a/lib/efi_loader/efi_device_path.c ++++ b/lib/efi_loader/efi_device_path.c +@@ -351,6 +351,70 @@ struct efi_device_path *efi_dp_create_device_node(const u8 type, + return ret; + } + ++struct efi_device_path *efi_dp_append_instance( ++ const struct efi_device_path *dp, ++ const struct efi_device_path *dpi) ++{ ++ size_t sz, szi; ++ struct efi_device_path *p, *ret; ++ ++ if (!dpi) ++ return NULL; ++ if (!dp) ++ return efi_dp_dup(dpi); ++ sz = efi_dp_size(dp); ++ szi = efi_dp_instance_size(dpi); ++ p = dp_alloc(sz + szi + 2 * sizeof(END)); ++ if (!p) ++ return NULL; ++ ret = p; ++ memcpy(p, dp, sz + sizeof(END)); ++ p = (void *)p + sz; ++ p->sub_type = DEVICE_PATH_SUB_TYPE_INSTANCE_END; ++ p = (void *)p + sizeof(END); ++ memcpy(p, dpi, szi); ++ p = (void *)p + szi; ++ memcpy(p, &END, sizeof(END)); ++ return ret; ++} ++ ++struct efi_device_path *efi_dp_get_next_instance(struct efi_device_path **dp, ++ efi_uintn_t *size) ++{ ++ size_t sz; ++ struct efi_device_path *p; ++ ++ if (size) ++ *size = 0; ++ if (!dp || !*dp) ++ return NULL; ++ p = *dp; ++ sz = efi_dp_instance_size(*dp); ++ p = dp_alloc(sz + sizeof(END)); ++ if (!p) ++ return NULL; ++ memcpy(p, *dp, sz + sizeof(END)); ++ *dp = (void *)*dp + sz; ++ if ((*dp)->sub_type == DEVICE_PATH_SUB_TYPE_INSTANCE_END) ++ *dp = (void *)*dp + sizeof(END); ++ else ++ *dp = NULL; ++ if (size) ++ *size = sz + sizeof(END); ++ return p; ++} ++ ++bool efi_dp_is_multi_instance(const struct efi_device_path *dp) ++{ ++ const struct efi_device_path *p = dp; ++ ++ if (!p) ++ return false; ++ while (p->type != DEVICE_PATH_TYPE_END) ++ p = (void *)p + p->length; ++ return p->sub_type == DEVICE_PATH_SUB_TYPE_INSTANCE_END; ++} ++ + #ifdef CONFIG_DM + /* size of device-path not including END node for device and all parents + * up to the root device. +diff --git a/lib/efi_loader/efi_device_path_utilities.c b/lib/efi_loader/efi_device_path_utilities.c +index e73188b242..0ada2111db 100644 +--- a/lib/efi_loader/efi_device_path_utilities.c ++++ b/lib/efi_loader/efi_device_path_utilities.c +@@ -12,62 +12,158 @@ + const efi_guid_t efi_guid_device_path_utilities_protocol = + EFI_DEVICE_PATH_UTILITIES_PROTOCOL_GUID; + ++/* ++ * Get size of a device path. ++ * ++ * This function implements the GetDevicePathSize service of the device path ++ * utilities protocol. The device path length includes the end of path tag ++ * which may be an instance end. ++ * ++ * See the Unified Extensible Firmware Interface (UEFI) specification ++ * for details. ++ * ++ * @device_path device path ++ * @return size in bytes ++ */ + static efi_uintn_t EFIAPI get_device_path_size( + const struct efi_device_path *device_path) + { + efi_uintn_t sz = 0; + +- EFI_ENTRY("%p", device_path); ++ EFI_ENTRY("%pD", device_path); + /* size includes the END node: */ + if (device_path) + sz = efi_dp_size(device_path) + sizeof(struct efi_device_path); + return EFI_EXIT(sz); + } + ++/* ++ * Duplicate a device path. ++ * ++ * This function implements the DuplicateDevicePath service of the device path ++ * utilities protocol. ++ * ++ * The UEFI spec does not indicate what happens to the end tag. We follow the ++ * EDK2 logic: In case the device path ends with an end of instance tag, the ++ * copy will also end with an end of instance tag. ++ * ++ * See the Unified Extensible Firmware Interface (UEFI) specification ++ * for details. ++ * ++ * @device_path device path ++ * @return copy of the device path ++ */ + static struct efi_device_path * EFIAPI duplicate_device_path( + const struct efi_device_path *device_path) + { +- EFI_ENTRY("%p", device_path); ++ EFI_ENTRY("%pD", device_path); + return EFI_EXIT(efi_dp_dup(device_path)); + } + ++/* ++ * Append device path. ++ * ++ * This function implements the AppendDevicePath service of the device path ++ * utilities protocol. ++ * ++ * See the Unified Extensible Firmware Interface (UEFI) specification ++ * for details. ++ * ++ * @src1 1st device path ++ * @src2 2nd device path ++ * @return concatenated device path ++ */ + static struct efi_device_path * EFIAPI append_device_path( + const struct efi_device_path *src1, + const struct efi_device_path *src2) + { +- EFI_ENTRY("%p, %p", src1, src2); ++ EFI_ENTRY("%pD, %pD", src1, src2); + return EFI_EXIT(efi_dp_append(src1, src2)); + } + ++/* ++ * Append device path node. ++ * ++ * This function implements the AppendDeviceNode service of the device path ++ * utilities protocol. ++ * ++ * See the Unified Extensible Firmware Interface (UEFI) specification ++ * for details. ++ * ++ * @device_path device path ++ * @device_node device node ++ * @return concatenated device path ++ */ + static struct efi_device_path * EFIAPI append_device_node( + const struct efi_device_path *device_path, + const struct efi_device_path *device_node) + { +- EFI_ENTRY("%p, %p", device_path, device_node); ++ EFI_ENTRY("%pD, %p", device_path, device_node); + return EFI_EXIT(efi_dp_append_node(device_path, device_node)); + } + ++/* ++ * Append device path instance. ++ * ++ * This function implements the AppendDevicePathInstance service of the device ++ * path utilities protocol. ++ * ++ * See the Unified Extensible Firmware Interface (UEFI) specification ++ * for details. ++ * ++ * @device_path 1st device path ++ * @device_path_instance 2nd device path ++ * @return concatenated device path ++ */ + static struct efi_device_path * EFIAPI append_device_path_instance( + const struct efi_device_path *device_path, + const struct efi_device_path *device_path_instance) + { +- EFI_ENTRY("%p, %p", device_path, device_path_instance); +- return EFI_EXIT(NULL); ++ EFI_ENTRY("%pD, %pD", device_path, device_path_instance); ++ return EFI_EXIT(efi_dp_append_instance(device_path, ++ device_path_instance)); + } + ++/* ++ * Get next device path instance. ++ * ++ * This function implements the GetNextDevicePathInstance service of the device ++ * path utilities protocol. ++ * ++ * See the Unified Extensible Firmware Interface (UEFI) specification ++ * for details. ++ * ++ * @device_path_instance next device path instance ++ * @device_path_instance_size size of the device path instance ++ * @return concatenated device path ++ */ + static struct efi_device_path * EFIAPI get_next_device_path_instance( + struct efi_device_path **device_path_instance, + efi_uintn_t *device_path_instance_size) + { +- EFI_ENTRY("%p, %p", device_path_instance, device_path_instance_size); +- return EFI_EXIT(NULL); ++ EFI_ENTRY("%pD, %p", device_path_instance, device_path_instance_size); ++ return EFI_EXIT(efi_dp_get_next_instance(device_path_instance, ++ device_path_instance_size)); + } + ++/* ++ * Check if a device path contains more than one instance. ++ * ++ * This function implements the AppendDeviceNode service of the device path ++ * utilities protocol. ++ * ++ * See the Unified Extensible Firmware Interface (UEFI) specification ++ * for details. ++ * ++ * @device_path device path ++ * @device_node device node ++ * @return concatenated device path ++ */ + static bool EFIAPI is_device_path_multi_instance( + const struct efi_device_path *device_path) + { +- EFI_ENTRY("%p", device_path); +- return EFI_EXIT(false); ++ EFI_ENTRY("%pD", device_path); ++ return EFI_EXIT(efi_dp_is_multi_instance(device_path)); + } + + /* +-- +2.17.0 + +From e83222bfc3ad2d7b2ecb1f1e559d78ec0d1f03cd Mon Sep 17 00:00:00 2001 +From: Heinrich Schuchardt +Date: Mon, 16 Apr 2018 07:59:10 +0200 +Subject: [PATCH 10/10] efi_selftest: test EFI_DEVICE_PATH_UTILITIES_PROTOCOL + +Provide unit tests for the EFI_DEVICE_PATH_UTILITIES_PROTOCOL. + +Signed-off-by: Heinrich Schuchardt +Signed-off-by: Alexander Graf +--- + lib/efi_selftest/Makefile | 1 + + .../efi_selftest_devicepath_util.c | 286 ++++++++++++++++++ + 2 files changed, 287 insertions(+) + create mode 100644 lib/efi_selftest/efi_selftest_devicepath_util.c + +diff --git a/lib/efi_selftest/Makefile b/lib/efi_selftest/Makefile +index 31b444fc8b..0e4980c8a0 100644 +--- a/lib/efi_selftest/Makefile ++++ b/lib/efi_selftest/Makefile +@@ -18,6 +18,7 @@ efi_selftest_bitblt.o \ + efi_selftest_controllers.o \ + efi_selftest_console.o \ + efi_selftest_devicepath.o \ ++efi_selftest_devicepath_util.o \ + efi_selftest_events.o \ + efi_selftest_event_groups.o \ + efi_selftest_exitbootservices.o \ +diff --git a/lib/efi_selftest/efi_selftest_devicepath_util.c b/lib/efi_selftest/efi_selftest_devicepath_util.c +new file mode 100644 +index 0000000000..2b5384f21b +--- /dev/null ++++ b/lib/efi_selftest/efi_selftest_devicepath_util.c +@@ -0,0 +1,286 @@ ++/* ++ * efi_selftest_devicepath_util ++ * ++ * Copyright (c) 2018 Heinrich Schuchardt ++ * ++ * SPDX-License-Identifier: GPL-2.0+ ++ * ++ * This unit test checks the device path utilities protocol. ++ */ ++ ++#include ++ ++static struct efi_boot_services *boottime; ++ ++static efi_guid_t guid_device_path_utilities_protocol = ++ EFI_DEVICE_PATH_UTILITIES_PROTOCOL_GUID; ++ ++struct efi_device_path_utilities_protocol *dpu; ++ ++/* ++ * Setup unit test. ++ * ++ * Locate the device path utilities protocol. ++ * ++ * @handle: handle of the loaded image ++ * @systable: system table ++ */ ++static int setup(const efi_handle_t img_handle, ++ const struct efi_system_table *systable) ++{ ++ int ret; ++ ++ boottime = systable->boottime; ++ ++ ret = boottime->locate_protocol(&guid_device_path_utilities_protocol, ++ NULL, (void **)&dpu); ++ if (ret != EFI_SUCCESS) { ++ dpu = NULL; ++ efi_st_error( ++ "Device path to text protocol is not available.\n"); ++ return EFI_ST_FAILURE; ++ } ++ ++ return EFI_ST_SUCCESS; ++} ++ ++/* ++ * Create a device path consisting of a single media device node followed by an ++ * end node. ++ * ++ * @length: length of the media device node ++ * @dp: device path ++ * @return: status code ++ */ ++static int create_single_node_device_path(unsigned int length, ++ struct efi_device_path **dp) ++{ ++ struct efi_device_path *node; ++ efi_uintn_t len; ++ int ret; ++ ++ node = dpu->create_device_node(DEVICE_PATH_TYPE_MEDIA_DEVICE, ++ DEVICE_PATH_SUB_TYPE_FILE_PATH, length); ++ if (!node) { ++ efi_st_error("CreateDeviceNode failed\n"); ++ return EFI_ST_FAILURE; ++ } ++ *dp = dpu->append_device_node(NULL, node); ++ if (!*dp) { ++ efi_st_error("AppendDeviceNode failed\n"); ++ return EFI_ST_FAILURE; ++ } ++ ret = boottime->free_pool(node); ++ if (ret != EFI_ST_SUCCESS) { ++ efi_st_error("FreePool failed\n"); ++ return EFI_ST_FAILURE; ++ } ++ len = dpu->get_device_path_size(*dp); ++ if (len != length + 4) { ++ efi_st_error("Wrong device path length %u, expected %u\n", ++ (unsigned int)len, length); ++ return EFI_ST_FAILURE; ++ } ++ return EFI_ST_SUCCESS; ++} ++ ++/* ++ * Execute unit test. ++ * ++ * In the test device paths are created, copied, and concatenated. The device ++ * path length is used as a measure of success. ++ */ ++static int execute(void) ++{ ++ struct efi_device_path *dp1; ++ struct efi_device_path *dp2; ++ struct efi_device_path *dp3; ++ ++ efi_uintn_t len; ++ int ret; ++ ++ /* IsDevicePathMultiInstance(NULL) */ ++ if (dpu->is_device_path_multi_instance(NULL)) { ++ efi_st_error("IsDevicePathMultiInstance(NULL) returned true\n"); ++ return EFI_ST_FAILURE; ++ } ++ /* GetDevicePathSize(NULL) */ ++ len = dpu->get_device_path_size(NULL); ++ if (len) { ++ efi_st_error("Wrong device path length %u, expected 0\n", ++ (unsigned int)len); ++ return EFI_ST_FAILURE; ++ } ++ /* DuplicateDevicePath(NULL) */ ++ dp1 = dpu->duplicate_device_path(NULL); ++ if (dp1) { ++ efi_st_error("DuplicateDevicePath(NULL) failed\n"); ++ return EFI_ST_FAILURE; ++ } ++ /* AppendDevicePath(NULL, NULL) */ ++ dp1 = dpu->append_device_path(NULL, NULL); ++ if (!dp1) { ++ efi_st_error("AppendDevicePath(NULL, NULL) failed\n"); ++ return EFI_ST_FAILURE; ++ } ++ len = dpu->get_device_path_size(dp1); ++ if (len != 4) { ++ efi_st_error("Wrong device path length %u, expected 4\n", ++ (unsigned int)len); ++ return EFI_ST_FAILURE; ++ } ++ ret = boottime->free_pool(dp1); ++ if (ret != EFI_ST_SUCCESS) { ++ efi_st_error("FreePool failed\n"); ++ return EFI_ST_FAILURE; ++ } ++ /* CreateDeviceNode */ ++ ret = create_single_node_device_path(21, &dp1); ++ if (ret != EFI_ST_SUCCESS) ++ return ret; ++ ret = create_single_node_device_path(17, &dp2); ++ if (ret != EFI_ST_SUCCESS) ++ return ret; ++ /* AppendDevicePath */ ++ dp3 = dpu->append_device_path(dp1, dp2); ++ if (!dp3) { ++ efi_st_error("AppendDevicePath failed\n"); ++ return EFI_ST_FAILURE; ++ } ++ if (dp3 == dp1 || dp3 == dp2) { ++ efi_st_error("AppendDevicePath reused buffer\n"); ++ return EFI_ST_FAILURE; ++ } ++ len = dpu->get_device_path_size(dp3); ++ /* 21 + 17 + 4 */ ++ if (len != 42) { ++ efi_st_error("Wrong device path length %u, expected 42\n", ++ (unsigned int)len); ++ return EFI_ST_FAILURE; ++ } ++ ret = boottime->free_pool(dp2); ++ if (ret != EFI_ST_SUCCESS) { ++ efi_st_error("FreePool failed\n"); ++ return EFI_ST_FAILURE; ++ } ++ /* AppendDeviceNode */ ++ dp2 = dpu->append_device_node(dp1, dp3); ++ if (!dp2) { ++ efi_st_error("AppendDevicePath failed\n"); ++ return EFI_ST_FAILURE; ++ } ++ len = dpu->get_device_path_size(dp2); ++ /* 21 + 21 + 4 */ ++ if (len != 46) { ++ printf("%s(%d) %s\n", __FILE__, __LINE__, __func__); ++ efi_st_error("Wrong device path length %u, expected 46\n", ++ (unsigned int)len); ++ return EFI_ST_FAILURE; ++ } ++ ret = boottime->free_pool(dp1); ++ if (ret != EFI_ST_SUCCESS) { ++ efi_st_error("FreePool failed\n"); ++ return EFI_ST_FAILURE; ++ } ++ /* IsDevicePathMultiInstance */ ++ if (dpu->is_device_path_multi_instance(dp2)) { ++ printf("%s(%d) %s\n", __FILE__, __LINE__, __func__); ++ efi_st_error("IsDevicePathMultiInstance returned true\n"); ++ return EFI_ST_FAILURE; ++ } ++ /* AppendDevicePathInstance */ ++ dp1 = dpu->append_device_path_instance(dp2, dp3); ++ if (!dp1) { ++ efi_st_error("AppendDevicePathInstance failed\n"); ++ return EFI_ST_FAILURE; ++ } ++ len = dpu->get_device_path_size(dp1); ++ /* 46 + 42 */ ++ if (len != 88) { ++ efi_st_error("Wrong device path length %u, expected 88\n", ++ (unsigned int)len); ++ return EFI_ST_FAILURE; ++ } ++ /* IsDevicePathMultiInstance */ ++ if (!dpu->is_device_path_multi_instance(dp1)) { ++ efi_st_error("IsDevicePathMultiInstance returned false\n"); ++ return EFI_ST_FAILURE; ++ } ++ ret = boottime->free_pool(dp2); ++ if (ret != EFI_ST_SUCCESS) { ++ efi_st_error("FreePool failed\n"); ++ return EFI_ST_FAILURE; ++ } ++ ret = boottime->free_pool(dp3); ++ if (ret != EFI_ST_SUCCESS) { ++ efi_st_error("FreePool failed\n"); ++ return EFI_ST_FAILURE; ++ } ++ /* GetNextDevicePathInstance */ ++ dp3 = dp1; ++ dp2 = dpu->get_next_device_path_instance(&dp1, &len); ++ if (!dp2) { ++ efi_st_error("GetNextDevicePathInstance failed\n"); ++ return EFI_ST_FAILURE; ++ } ++ if (!dp1) { ++ efi_st_error("GetNextDevicePathInstance no 2nd instance\n"); ++ return EFI_ST_FAILURE; ++ } ++ if (len != 46) { ++ efi_st_error("Wrong device path length %u, expected 46\n", ++ (unsigned int)len); ++ return EFI_ST_FAILURE; ++ } ++ len = dpu->get_device_path_size(dp1); ++ if (len != 42) { ++ efi_st_error("Wrong device path length %u, expected 42\n", ++ (unsigned int)len); ++ return EFI_ST_FAILURE; ++ } ++ ret = boottime->free_pool(dp2); ++ if (ret != EFI_ST_SUCCESS) { ++ efi_st_error("FreePool failed\n"); ++ return EFI_ST_FAILURE; ++ } ++ dp2 = dpu->get_next_device_path_instance(&dp1, &len); ++ if (!dp2) { ++ efi_st_error("GetNextDevicePathInstance failed\n"); ++ return EFI_ST_FAILURE; ++ } ++ if (len != 42) { ++ efi_st_error("Wrong device path length %u, expected 46\n", ++ (unsigned int)len); ++ return EFI_ST_FAILURE; ++ } ++ if (dp1) { ++ efi_st_error("GetNextDevicePathInstance did not signal end\n"); ++ return EFI_ST_FAILURE; ++ } ++ ret = boottime->free_pool(dp2); ++ if (ret != EFI_ST_SUCCESS) { ++ efi_st_error("FreePool failed\n"); ++ return EFI_ST_FAILURE; ++ } ++ ++ /* Clean up */ ++ ret = boottime->free_pool(dp2); ++ if (ret != EFI_ST_SUCCESS) { ++ efi_st_error("FreePool failed\n"); ++ return EFI_ST_FAILURE; ++ } ++ ret = boottime->free_pool(dp3); ++ if (ret != EFI_ST_SUCCESS) { ++ efi_st_error("FreePool failed\n"); ++ return EFI_ST_FAILURE; ++ } ++ ++ return EFI_ST_SUCCESS; ++} ++ ++EFI_UNIT_TEST(dputil) = { ++ .name = "device path utilities protocol", ++ .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT, ++ .setup = setup, ++ .execute = execute, ++}; +-- +2.17.0 +