1234 lines
38 KiB
Diff
1234 lines
38 KiB
Diff
From d8d8997bbce7ff81799cb20795bdf97db9f8d5f2 Mon Sep 17 00:00:00 2001
|
|
From: Heinrich Schuchardt <xypron.glpk@gmx.de>
|
|
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 <xypron.glpk@gmx.de>
|
|
Reviewed-by: Simon Glass <sjg@chromium.org>
|
|
Signed-off-by: Alexander Graf <agraf@suse.de>
|
|
---
|
|
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 <pbrobinson@gmail.com>
|
|
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 <pbrobinson@gmail.com>
|
|
---
|
|
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 <xypron.glpk@gmx.de>
|
|
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 <xypron.glpk@gmx.de>
|
|
Signed-off-by: Alexander Graf <agraf@suse.de>
|
|
---
|
|
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 <xypron.glpk@gmx.de>
|
|
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 <xypron.glpk@gmx.de>
|
|
Signed-off-by: Alexander Graf <agraf@suse.de>
|
|
---
|
|
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 <xypron.glpk@gmx.de>
|
|
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 <xypron.glpk@gmx.de>
|
|
Signed-off-by: Alexander Graf <agraf@suse.de>
|
|
---
|
|
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 <xypron.glpk@gmx.de>
|
|
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 <xypron.glpk@gmx.de>
|
|
Signed-off-by: Alexander Graf <agraf@suse.de>
|
|
---
|
|
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 <xypron.glpk@gmx.de>
|
|
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 <xypron.glpk@gmx.de>
|
|
Signed-off-by: Alexander Graf <agraf@suse.de>
|
|
---
|
|
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 <xypron.glpk@gmx.de>
|
|
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 <xypron.glpk@gmx.de>
|
|
Signed-off-by: Alexander Graf <agraf@suse.de>
|
|
---
|
|
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 <xypron.glpk@gmx.de>
|
|
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 <xypron.glpk@gmx.de>
|
|
Signed-off-by: Alexander Graf <agraf@suse.de>
|
|
---
|
|
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 <xypron.glpk@gmx.de>
|
|
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 <xypron.glpk@gmx.de>
|
|
Signed-off-by: Alexander Graf <agraf@suse.de>
|
|
---
|
|
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 <xypron.glpk@gmx.de>
|
|
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 <xypron.glpk@gmx.de>
|
|
Signed-off-by: Alexander Graf <agraf@suse.de>
|
|
---
|
|
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 <xypron.glpk@gmx.de>
|
|
+ *
|
|
+ * SPDX-License-Identifier: GPL-2.0+
|
|
+ *
|
|
+ * This unit test checks the device path utilities protocol.
|
|
+ */
|
|
+
|
|
+#include <efi_selftest.h>
|
|
+
|
|
+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
|
|
|