efi_selftest: unit test for RegisterProtocolNotify()
Provide a unit test for the RegisterProtocolNotify() boot service. Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
This commit is contained in:
parent
ab15d4149e
commit
24f6be7ada
2 changed files with 232 additions and 0 deletions
|
@ -27,6 +27,7 @@ efi_selftest_gop.o \
|
|||
efi_selftest_loaded_image.o \
|
||||
efi_selftest_manageprotocols.o \
|
||||
efi_selftest_memory.o \
|
||||
efi_selftest_register_notify.o \
|
||||
efi_selftest_rtc.o \
|
||||
efi_selftest_snp.o \
|
||||
efi_selftest_textinput.o \
|
||||
|
|
231
lib/efi_selftest/efi_selftest_register_notify.c
Normal file
231
lib/efi_selftest/efi_selftest_register_notify.c
Normal file
|
@ -0,0 +1,231 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* efi_selftest_register_notify
|
||||
*
|
||||
* Copyright (c) 2019 Heinrich Schuchardt <xypron.glpk@gmx.de>
|
||||
*
|
||||
* This unit test checks the following protocol services:
|
||||
* InstallProtocolInterface, UninstallProtocolInterface,
|
||||
* RegisterProtocolNotify, CreateEvent, CloseEvent.
|
||||
*/
|
||||
|
||||
#include <efi_selftest.h>
|
||||
|
||||
/*
|
||||
* The test currently does not actually call the interface function.
|
||||
* So this is just a dummy structure.
|
||||
*/
|
||||
struct interface {
|
||||
void (EFIAPI * inc)(void);
|
||||
};
|
||||
|
||||
struct context {
|
||||
void *registration_key;
|
||||
efi_uintn_t notify_count;
|
||||
efi_uintn_t handle_count;
|
||||
efi_handle_t *handles;
|
||||
};
|
||||
|
||||
static struct efi_boot_services *boottime;
|
||||
static efi_guid_t guid1 =
|
||||
EFI_GUID(0x2e7ca819, 0x21d3, 0x0a3a,
|
||||
0xf7, 0x91, 0x82, 0x1f, 0x7a, 0x83, 0x67, 0xaf);
|
||||
static efi_guid_t guid2 =
|
||||
EFI_GUID(0xf909f2bb, 0x90a8, 0x0d77,
|
||||
0x94, 0x0c, 0x3e, 0xa8, 0xea, 0x38, 0xd6, 0x6f);
|
||||
static struct context context;
|
||||
static struct efi_event *event;
|
||||
|
||||
/*
|
||||
* Notification function, increments the notification count if parameter
|
||||
* context is provided.
|
||||
*
|
||||
* @event notified event
|
||||
* @context pointer to the notification count
|
||||
*/
|
||||
static void EFIAPI notify(struct efi_event *event, void *context)
|
||||
{
|
||||
struct context *cp = context;
|
||||
efi_status_t ret;
|
||||
|
||||
cp->notify_count++;
|
||||
|
||||
ret = boottime->locate_handle_buffer(BY_REGISTER_NOTIFY, NULL,
|
||||
cp->registration_key,
|
||||
&cp->handle_count,
|
||||
&cp->handles);
|
||||
if (ret != EFI_SUCCESS)
|
||||
cp->handle_count = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup unit test.
|
||||
*
|
||||
* @handle: handle of the loaded image
|
||||
* @systable: system table
|
||||
*/
|
||||
static int setup(const efi_handle_t img_handle,
|
||||
const struct efi_system_table *systable)
|
||||
{
|
||||
efi_status_t ret;
|
||||
|
||||
boottime = systable->boottime;
|
||||
|
||||
ret = boottime->create_event(EVT_NOTIFY_SIGNAL,
|
||||
TPL_CALLBACK, notify, &context,
|
||||
&event);
|
||||
if (ret != EFI_SUCCESS) {
|
||||
efi_st_error("could not create event\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
|
||||
ret = boottime->register_protocol_notify(&guid1, event,
|
||||
&context.registration_key);
|
||||
if (ret != EFI_SUCCESS) {
|
||||
efi_st_error("could not register event\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
|
||||
return EFI_ST_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Tear down unit test.
|
||||
*
|
||||
*/
|
||||
static int teardown(void)
|
||||
{
|
||||
efi_status_t ret;
|
||||
|
||||
if (event) {
|
||||
ret = boottime->close_event(event);
|
||||
event = NULL;
|
||||
if (ret != EFI_SUCCESS) {
|
||||
efi_st_error("could not close event\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
return EFI_ST_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Execute unit test.
|
||||
*
|
||||
*/
|
||||
static int execute(void)
|
||||
{
|
||||
efi_status_t ret;
|
||||
efi_handle_t handle1 = NULL, handle2 = NULL;
|
||||
struct interface interface1, interface2;
|
||||
|
||||
ret = boottime->install_protocol_interface(&handle1, &guid1,
|
||||
EFI_NATIVE_INTERFACE,
|
||||
&interface1);
|
||||
if (ret != EFI_SUCCESS) {
|
||||
efi_st_error("could not install interface\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
if (!context.notify_count) {
|
||||
efi_st_error("install was not notified\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
if (context.notify_count > 1) {
|
||||
efi_st_error("install was notified too often\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
if (context.handle_count != 1) {
|
||||
efi_st_error("LocateHandle failed\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
ret = boottime->free_pool(context.handles);
|
||||
if (ret != EFI_SUCCESS) {
|
||||
efi_st_error("FreePool failed\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
context.notify_count = 0;
|
||||
ret = boottime->install_protocol_interface(&handle1, &guid2,
|
||||
EFI_NATIVE_INTERFACE,
|
||||
&interface1);
|
||||
if (ret != EFI_SUCCESS) {
|
||||
efi_st_error("could not install interface\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
if (context.notify_count) {
|
||||
efi_st_error("wrong protocol was notified\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
context.notify_count = 0;
|
||||
ret = boottime->reinstall_protocol_interface(handle1, &guid1,
|
||||
&interface1, &interface2);
|
||||
if (ret != EFI_SUCCESS) {
|
||||
efi_st_error("could not reinstall interface\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
if (!context.notify_count) {
|
||||
efi_st_error("reinstall was not notified\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
if (context.notify_count > 1) {
|
||||
efi_st_error("reinstall was notified too often\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
if (context.handle_count != 1) {
|
||||
efi_st_error("LocateHandle failed\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
ret = boottime->free_pool(context.handles);
|
||||
if (ret != EFI_SUCCESS) {
|
||||
efi_st_error("FreePool failed\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
context.notify_count = 0;
|
||||
ret = boottime->install_protocol_interface(&handle2, &guid1,
|
||||
EFI_NATIVE_INTERFACE,
|
||||
&interface1);
|
||||
if (ret != EFI_SUCCESS) {
|
||||
efi_st_error("could not install interface\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
if (!context.notify_count) {
|
||||
efi_st_error("install was not notified\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
if (context.notify_count > 1) {
|
||||
efi_st_error("install was notified too often\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
if (context.handle_count != 2) {
|
||||
efi_st_error("LocateHandle failed\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
ret = boottime->free_pool(context.handles);
|
||||
if (ret != EFI_SUCCESS) {
|
||||
efi_st_error("FreePool failed\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
|
||||
ret = boottime->uninstall_multiple_protocol_interfaces
|
||||
(handle1, &guid1, &interface2,
|
||||
&guid2, &interface1, NULL);
|
||||
if (ret != EFI_SUCCESS) {
|
||||
efi_st_error("UninstallMultipleProtocolInterfaces failed\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
ret = boottime->uninstall_multiple_protocol_interfaces
|
||||
(handle2, &guid1, &interface1, NULL);
|
||||
if (ret != EFI_SUCCESS) {
|
||||
efi_st_error("UninstallMultipleProtocolInterfaces failed\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
|
||||
return EFI_ST_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_UNIT_TEST(regprotnot) = {
|
||||
.name = "register protocol notify",
|
||||
.phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
|
||||
.setup = setup,
|
||||
.execute = execute,
|
||||
.teardown = teardown,
|
||||
};
|
Loading…
Reference in a new issue