[U-Boot] [PATCH 2/2] efi_selftest: EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE

Heinrich Schuchardt xypron.glpk at gmx.de
Sat Jul 13 06:05:42 UTC 2019


Provide a unit test for SetVirtualAddressMap() and ConvertPointer().
As ConvertPointer() is not implemented yet this will spit out some
warnings.

Signed-off-by: Heinrich Schuchardt <xypron.glpk at gmx.de>
---
 lib/efi_selftest/Makefile                     |   1 +
 .../efi_selftest_set_virtual_address_map.c    | 192 ++++++++++++++++++
 2 files changed, 193 insertions(+)
 create mode 100644 lib/efi_selftest/efi_selftest_set_virtual_address_map.c

diff --git a/lib/efi_selftest/Makefile b/lib/efi_selftest/Makefile
index 88678755cc..5d7a1643ef 100644
--- a/lib/efi_selftest/Makefile
+++ b/lib/efi_selftest/Makefile
@@ -28,6 +28,7 @@ efi_selftest_manageprotocols.o \
 efi_selftest_memory.o \
 efi_selftest_open_protocol.o \
 efi_selftest_register_notify.o \
+efi_selftest_set_virtual_address_map.o \
 efi_selftest_snp.o \
 efi_selftest_textinput.o \
 efi_selftest_textinputex.o \
diff --git a/lib/efi_selftest/efi_selftest_set_virtual_address_map.c b/lib/efi_selftest/efi_selftest_set_virtual_address_map.c
new file mode 100644
index 0000000000..5ebcdd2428
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_set_virtual_address_map.c
@@ -0,0 +1,192 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * efi_selftest_set_virtual_address_map.c
+ *
+ * Copyright (c) 2019 Heinrich Schuchardt <xypron.glpk at gmx.de>
+ *
+ * This test checks the notification of EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE
+ * and the following services: SetVirtualAddressMap, ConvertPointer.
+ */
+
+#include <efi_selftest.h>
+
+static const struct efi_boot_services *boottime;
+static const struct efi_runtime_services *runtime;
+static struct efi_event *event;
+static struct efi_mem_desc *memory_map;
+static efi_uintn_t map_size;
+static efi_uintn_t desc_size;
+static u32 desc_version;
+static u64 page1;
+static u64 page2;
+static u32 notify_call_count;
+
+/**
+ * notify () - notification function
+ *
+ * This function is called when the EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event
+ * occurs. The correct output of ConvertPointer() is checked.
+ *
+ * @event	notified event
+ * @context	pointer to the notification count
+ */
+static void EFIAPI notify(struct efi_event *event, void *context)
+{
+	void *addr;
+	efi_status_t ret;
+
+	++notify_call_count;
+
+	addr = (void *)(uintptr_t)page1;
+	ret = runtime->convert_pointer(0, &addr);
+	if (ret != EFI_SUCCESS)
+		efi_st_todo("ConvertPointer failed\n");
+	if ((uintptr_t)addr != page1 + EFI_PAGE_SIZE)
+		efi_st_todo("ConvertPointer wrong address\n");
+
+	addr = (void *)(uintptr_t)page2;
+	ret = runtime->convert_pointer(0, &addr);
+	if (ret != EFI_SUCCESS)
+		efi_st_todo("ConvertPointer failed\n");
+	if ((uintptr_t)addr != page2 + 2 * EFI_PAGE_SIZE)
+		efi_st_todo("ConvertPointer wrong address\n");
+}
+
+/**
+ * setup() - setup unit test
+ *
+ * The memory map is read. Boottime only entries are deleted. Two entries for
+ * newly allocated pages are added. For these virtual addresses deviating from
+ * the physical addresses are set.
+ *
+ * @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)
+{
+	efi_uintn_t map_key;
+	efi_status_t ret;
+	struct efi_mem_desc *end, *pos1, *pos2;
+
+	boottime = systable->boottime;
+	runtime = systable->runtime;
+
+	ret = boottime->create_event(EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE,
+				     TPL_CALLBACK, notify, NULL,
+				     &event);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("could not create event\n");
+		return EFI_ST_FAILURE;
+	}
+
+	ret = boottime->get_memory_map(&map_size, NULL, &map_key, &desc_size,
+				       &desc_version);
+	if (ret != EFI_BUFFER_TOO_SMALL) {
+		efi_st_error(
+			"GetMemoryMap did not return EFI_BUFFER_TOO_SMALL\n");
+		return EFI_ST_FAILURE;
+	}
+	/* Allocate extra space for newly allocated memory */
+	map_size += 3 * sizeof(struct efi_mem_desc);
+	ret = boottime->allocate_pool(EFI_BOOT_SERVICES_DATA, map_size,
+				      (void **)&memory_map);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("AllocatePool failed\n");
+		return EFI_ST_FAILURE;
+	}
+	ret = boottime->get_memory_map(&map_size, memory_map, &map_key,
+				       &desc_size, &desc_version);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("GetMemoryMap failed\n");
+		return EFI_ST_FAILURE;
+	}
+	ret = boottime->allocate_pages(EFI_ALLOCATE_ANY_PAGES,
+				       EFI_BOOT_SERVICES_DATA, 2, &page1);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("AllocatePages failed\n");
+		return EFI_ST_FAILURE;
+	}
+	ret = boottime->allocate_pages(EFI_ALLOCATE_ANY_PAGES,
+				       EFI_BOOT_SERVICES_DATA, 3, &page2);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("AllocatePages failed\n");
+		return EFI_ST_FAILURE;
+	}
+	/* Remove entries not relevant for runtime from map */
+	end = (struct efi_mem_desc *)((u8 *)memory_map + map_size);
+	for (pos1 = memory_map, pos2 = memory_map;
+	     pos2 < end; ++pos2) {
+		switch (pos2->type) {
+		case EFI_LOADER_CODE:
+		case EFI_LOADER_DATA:
+		case EFI_BOOT_SERVICES_CODE:
+		case EFI_BOOT_SERVICES_DATA:
+			continue;
+		}
+		memcpy(pos1, pos2, desc_size);
+		++pos1;
+	}
+
+	/*
+	 * Add entries with virtual addresses deviating from the physical
+	 * addresses. By choosing virtual address ranges within the allocated
+	 * physical pages address space collisions are avoided.
+	 */
+	pos1->type = EFI_RUNTIME_SERVICES_DATA;
+	pos1->reserved = 0;
+	pos1->physical_start = page1;
+	pos1->virtual_start = page1 + EFI_PAGE_SIZE;
+	pos1->num_pages = 1;
+	pos1->attribute = EFI_MEMORY_RUNTIME;
+	++pos1;
+
+	pos1->type = EFI_RUNTIME_SERVICES_DATA;
+	pos1->reserved = 0;
+	pos1->physical_start = page2;
+	pos1->virtual_start = page2 + 2 * EFI_PAGE_SIZE;
+	pos1->num_pages = 1;
+	pos1->attribute = EFI_MEMORY_RUNTIME;
+	++pos1;
+
+	map_size = (u8 *)pos1 - (u8 *)memory_map;
+
+	return EFI_ST_SUCCESS;
+}
+
+/**
+ * execute() - execute unit test
+ *
+ * SetVirtualAddressMap() is called with the memory map prepared in setup().
+ *
+ * The triggering of the EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event is checked via
+ * the call count of the notification function.
+ *
+ * @return:	EFI_ST_SUCCESS for success
+ */
+static int execute(void)
+{
+	efi_status_t ret;
+
+	ret = runtime->set_virtual_address_map(map_size, desc_size,
+					       desc_version, memory_map);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("SetVirtualAddressMap failed\n");
+		return EFI_ST_FAILURE;
+	}
+	if (notify_call_count != 1) {
+		efi_st_error("EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE triggered %d times\n",
+			     notify_call_count);
+		return EFI_ST_FAILURE;
+	}
+
+	return EFI_ST_SUCCESS;
+}
+
+EFI_UNIT_TEST(virtaddrmap) = {
+	.name = "virtual address map",
+	.phase = EFI_SETUP_BEFORE_BOOTTIME_EXIT,
+	.setup = setup,
+	.execute = execute,
+};
--
2.20.1



More information about the U-Boot mailing list