summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/efi_loader/efi_bootmgr.c6
-rw-r--r--lib/efi_loader/efi_device_path.c33
-rw-r--r--lib/efi_loader/efi_runtime.c7
-rw-r--r--lib/efi_selftest/Makefile1
-rw-r--r--lib/efi_selftest/efi_selftest.c10
-rw-r--r--lib/efi_selftest/efi_selftest_reset.c58
-rw-r--r--lib/sscanf.c3
7 files changed, 108 insertions, 10 deletions
diff --git a/lib/efi_loader/efi_bootmgr.c b/lib/efi_loader/efi_bootmgr.c
index 1e06e60963..61dc72a23d 100644
--- a/lib/efi_loader/efi_bootmgr.c
+++ b/lib/efi_loader/efi_bootmgr.c
@@ -105,10 +105,8 @@ efi_status_t efi_deserialize_load_option(struct efi_load_option *lo, u8 *data,
if (*size < len)
return EFI_INVALID_PARAMETER;
lo->file_path = (struct efi_device_path *)data;
- /*
- * TODO: validate device path. There should be an end node within
- * the indicated file_path_length.
- */
+ if (efi_dp_check_length(lo->file_path, len) < 0)
+ return EFI_INVALID_PARAMETER;
data += len;
*size -= len;
diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c
index 7ae14f3423..8a5c13c424 100644
--- a/lib/efi_loader/efi_device_path.c
+++ b/lib/efi_loader/efi_device_path.c
@@ -1127,3 +1127,36 @@ efi_status_t efi_dp_from_name(const char *dev, const char *devnr,
return EFI_SUCCESS;
}
+
+/**
+ * efi_dp_check_length() - check length of a device path
+ *
+ * @dp: pointer to device path
+ * @maxlen: maximum length of the device path
+ * Return:
+ * * length of the device path if it is less or equal @maxlen
+ * * -1 if the device path is longer then @maxlen
+ * * -1 if a device path node has a length of less than 4
+ * * -EINVAL if maxlen exceeds SSIZE_MAX
+ */
+ssize_t efi_dp_check_length(const struct efi_device_path *dp,
+ const size_t maxlen)
+{
+ ssize_t ret = 0;
+ u16 len;
+
+ if (maxlen > SSIZE_MAX)
+ return -EINVAL;
+ for (;;) {
+ len = dp->length;
+ if (len < 4)
+ return -1;
+ ret += len;
+ if (ret > maxlen)
+ return -1;
+ if (dp->type == DEVICE_PATH_TYPE_END &&
+ dp->sub_type == DEVICE_PATH_SUB_TYPE_END)
+ return ret;
+ dp = (const struct efi_device_path *)((const u8 *)dp + len);
+ }
+}
diff --git a/lib/efi_loader/efi_runtime.c b/lib/efi_loader/efi_runtime.c
index 78fd8014d9..dea2b4e5ee 100644
--- a/lib/efi_loader/efi_runtime.c
+++ b/lib/efi_loader/efi_runtime.c
@@ -365,7 +365,9 @@ out:
* efi_reset_system() - reset system
*
* This function implements the ResetSystem() runtime service after
- * SetVirtualAddressMap() is called. It only executes an endless loop.
+ * SetVirtualAddressMap() is called. As this placeholder cannot reset the
+ * system it simply return to the caller.
+ *
* Boards may override the helpers below to implement reset functionality.
*
* See the Unified Extensible Firmware Interface (UEFI) specification for
@@ -381,8 +383,7 @@ void __weak __efi_runtime EFIAPI efi_reset_system(
efi_status_t reset_status,
unsigned long data_size, void *reset_data)
{
- /* Nothing we can do */
- while (1) { }
+ return;
}
/**
diff --git a/lib/efi_selftest/Makefile b/lib/efi_selftest/Makefile
index 45ce6859b8..85fe8e1216 100644
--- a/lib/efi_selftest/Makefile
+++ b/lib/efi_selftest/Makefile
@@ -31,6 +31,7 @@ efi_selftest_mem.o \
efi_selftest_memory.o \
efi_selftest_open_protocol.o \
efi_selftest_register_notify.o \
+efi_selftest_reset.o \
efi_selftest_set_virtual_address_map.o \
efi_selftest_textinput.o \
efi_selftest_textinputex.o \
diff --git a/lib/efi_selftest/efi_selftest.c b/lib/efi_selftest/efi_selftest.c
index 5b01610eca..6eec8ae2a7 100644
--- a/lib/efi_selftest/efi_selftest.c
+++ b/lib/efi_selftest/efi_selftest.c
@@ -5,6 +5,7 @@
* Copyright (c) 2017 Heinrich Schuchardt <xypron.glpk@gmx.de>
*/
+#include <command.h>
#include <efi_selftest.h>
#include <vsprintf.h>
@@ -309,8 +310,13 @@ efi_status_t EFIAPI efi_selftest(efi_handle_t image_handle,
/* Reset system */
efi_st_printf("Preparing for reset. Press any key...\n");
efi_st_get_key();
- runtime->reset_system(EFI_RESET_WARM, EFI_NOT_READY,
- sizeof(reset_message), reset_message);
+
+ if (IS_ENABLED(CONFIG_EFI_HAVE_RUNTIME_RESET))
+ runtime->reset_system(EFI_RESET_WARM, EFI_NOT_READY,
+ sizeof(reset_message), reset_message);
+ else
+ do_reset(NULL, 0, 0, NULL);
+
efi_st_printf("\n");
efi_st_error("Reset failed\n");
diff --git a/lib/efi_selftest/efi_selftest_reset.c b/lib/efi_selftest/efi_selftest_reset.c
new file mode 100644
index 0000000000..8b6ac24cb1
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_reset.c
@@ -0,0 +1,58 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * efi_selftest_reset
+ *
+ * Copyright (c) 2020 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * This test checks the following service at boot time or runtime:
+ * ResetSystem()
+ */
+
+#include <efi_selftest.h>
+
+static struct efi_runtime_services *runtime;
+
+/*
+ * Setup unit test.
+ *
+ * @handle: handle of the loaded image
+ * @systable: system table
+ * @return: EFI_ST_SUCCESS for success
+ */
+static int setup(const efi_handle_t handle,
+ const struct efi_system_table *systable)
+{
+ runtime = systable->runtime;
+ return EFI_ST_SUCCESS;
+}
+
+/*
+ * Execute unit test.
+ *
+ * @return: EFI_ST_SUCCESS for success
+ */
+static int execute(void)
+{
+ u16 reset_data[] = L"Reset by selftest";
+
+ runtime->reset_system(EFI_RESET_COLD, EFI_SUCCESS,
+ sizeof(reset_data), reset_data);
+ efi_st_error("Reset failed.\n");
+ return EFI_ST_FAILURE;
+}
+
+EFI_UNIT_TEST(reset) = {
+ .name = "reset system",
+ .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
+ .setup = setup,
+ .execute = execute,
+ .on_request = true,
+};
+
+EFI_UNIT_TEST(resetrt) = {
+ .name = "reset system runtime",
+ .phase = EFI_SETUP_BEFORE_BOOTTIME_EXIT,
+ .setup = setup,
+ .execute = execute,
+ .on_request = true,
+};
diff --git a/lib/sscanf.c b/lib/sscanf.c
index d1e2dc272c..4c35c035fe 100644
--- a/lib/sscanf.c
+++ b/lib/sscanf.c
@@ -555,7 +555,8 @@ literal:
if (flags & SUPPRESS) {
size_t sum = 0;
- if ((n = inr) < width) {
+ n = inr;
+ if (n < width) {
sum += n;
width -= n;
inp += n;