mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-10 23:24:38 +00:00
efi_selftest: EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE
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@gmx.de>
This commit is contained in:
parent
14b40487ab
commit
112464f325
2 changed files with 193 additions and 0 deletions
|
@ -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 \
|
||||
|
|
192
lib/efi_selftest/efi_selftest_set_virtual_address_map.c
Normal file
192
lib/efi_selftest/efi_selftest_set_virtual_address_map.c
Normal file
|
@ -0,0 +1,192 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* efi_selftest_set_virtual_address_map.c
|
||||
*
|
||||
* Copyright (c) 2019 Heinrich Schuchardt <xypron.glpk@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,
|
||||
};
|
Loading…
Reference in a new issue