mirror of
https://github.com/Fishwaldo/u-boot.git
synced 2025-04-01 12:01:31 +00:00
Pull request for UEFI sub-system for v2019.07-rc2 (2)
Fix a bunch of errors in the UEFI sub-system: * implement missing UnloadImage(), * implement missing RegisterProtocolNotify(), * unload images in Exit(), * parameter checks. Provide a unit test for UnloadImage(). Remove a redundant function for unit tests. Clean up the UEFI sub-system initialization -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEbcT5xx8ppvoGt20zxIHbvCwFGsQFAlzSbVcACgkQxIHbvCwF GsTU5g/+Neyv0zcVdtqutCP3/GjPnDfGTkQBXGh8nXZW+57Ld4lhEYgNV6wQXcIE VSfUe6KQoTYDsfMRliT+ACytP2y70ZlVMR+qFsA9VX+TummeojWrJ892yj1eIu8R GBj+aEul5kBwegW+ZEuFogXC7UI6tVcrsQsTrypyjWyz1An8CxaOPwfntnJ2Ln8I lJZ9PZX5r62Sj5i72xcq5c6nxKzSnW0LAKLJTpTBpAAksdz0AAb3blwEnkFZiF+6 U44901/qBo7CORnkgwhoR+fK0HAecEaYHC98oCFQ0ARRKTaRvbG2U070V016nUK+ IY/6Ni43fZRKrb05p/OaB19y7HvhBDMH+XmY2DlNv5r5n/ZKRYxFcLDM4RUu/G7h q21h53DutZg/+DVif3UBGlUhLOh4lvw9n4TwEfF3a/ujQasL2IUGM7jMaq5h1Kbb NzyN1UCeQ5to80uh80FTXf8j5yk1zbRrOnTUdvMpgFLxIHuHThkjpdnjBvxBEiUy 5RVjhuMMtZ7cOnOvoUNhVX7+xJv4ig8+SEJd6VU3p3a/5Cji5mbufUQDmRy4NX++ E+2w+uqO998A7HaYJVHCDBT8SdZ1wg2hkxieN+4wrTGhZzu/2/p/93A2JMWQegC5 jJDsXEPJWembUpEoKevad6VbtW30USn5wHMk1vA/rPeccYvl1EM= =4a34 -----END PGP SIGNATURE----- Merge tag 'efi-2019-07-rc2-2' of git://git.denx.de/u-boot-efi Pull request for UEFI sub-system for v2019.07-rc2 (2) Fix a bunch of errors in the UEFI sub-system: * implement missing UnloadImage(), * implement missing RegisterProtocolNotify(), * unload images in Exit(), * parameter checks. Provide a unit test for UnloadImage(). Remove a redundant function for unit tests. Clean up the UEFI sub-system initialization
This commit is contained in:
commit
d4c352138c
20 changed files with 574 additions and 180 deletions
|
@ -6,7 +6,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <common.h>
|
#include <common.h>
|
||||||
#include <bootm.h>
|
|
||||||
#include <charset.h>
|
#include <charset.h>
|
||||||
#include <command.h>
|
#include <command.h>
|
||||||
#include <dm.h>
|
#include <dm.h>
|
||||||
|
@ -17,9 +16,7 @@
|
||||||
#include <linux/libfdt_env.h>
|
#include <linux/libfdt_env.h>
|
||||||
#include <mapmem.h>
|
#include <mapmem.h>
|
||||||
#include <memalign.h>
|
#include <memalign.h>
|
||||||
#include <asm/global_data.h>
|
|
||||||
#include <asm-generic/sections.h>
|
#include <asm-generic/sections.h>
|
||||||
#include <asm-generic/unaligned.h>
|
|
||||||
#include <linux/linkage.h>
|
#include <linux/linkage.h>
|
||||||
|
|
||||||
DECLARE_GLOBAL_DATA_PTR;
|
DECLARE_GLOBAL_DATA_PTR;
|
||||||
|
@ -27,15 +24,6 @@ DECLARE_GLOBAL_DATA_PTR;
|
||||||
static struct efi_device_path *bootefi_image_path;
|
static struct efi_device_path *bootefi_image_path;
|
||||||
static struct efi_device_path *bootefi_device_path;
|
static struct efi_device_path *bootefi_device_path;
|
||||||
|
|
||||||
/*
|
|
||||||
* Allow unaligned memory access.
|
|
||||||
*
|
|
||||||
* This routine is overridden by architectures providing this feature.
|
|
||||||
*/
|
|
||||||
void __weak allow_unaligned(void)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set the load options of an image from an environment variable.
|
* Set the load options of an image from an environment variable.
|
||||||
*
|
*
|
||||||
|
@ -338,11 +326,6 @@ static int do_efibootmgr(const char *fdt_opt)
|
||||||
efi_handle_t handle;
|
efi_handle_t handle;
|
||||||
efi_status_t ret;
|
efi_status_t ret;
|
||||||
|
|
||||||
/* Allow unaligned memory access */
|
|
||||||
allow_unaligned();
|
|
||||||
|
|
||||||
switch_to_non_secure_mode();
|
|
||||||
|
|
||||||
/* Initialize EFI drivers */
|
/* Initialize EFI drivers */
|
||||||
ret = efi_init_obj_list();
|
ret = efi_init_obj_list();
|
||||||
if (ret != EFI_SUCCESS) {
|
if (ret != EFI_SUCCESS) {
|
||||||
|
@ -391,11 +374,6 @@ static int do_bootefi_image(const char *image_opt, const char *fdt_opt)
|
||||||
efi_handle_t mem_handle = NULL, handle;
|
efi_handle_t mem_handle = NULL, handle;
|
||||||
efi_status_t ret;
|
efi_status_t ret;
|
||||||
|
|
||||||
/* Allow unaligned memory access */
|
|
||||||
allow_unaligned();
|
|
||||||
|
|
||||||
switch_to_non_secure_mode();
|
|
||||||
|
|
||||||
/* Initialize EFI drivers */
|
/* Initialize EFI drivers */
|
||||||
ret = efi_init_obj_list();
|
ret = efi_init_obj_list();
|
||||||
if (ret != EFI_SUCCESS) {
|
if (ret != EFI_SUCCESS) {
|
||||||
|
@ -582,11 +560,6 @@ static int do_efi_selftest(const char *fdt_opt)
|
||||||
struct efi_loaded_image *loaded_image_info;
|
struct efi_loaded_image *loaded_image_info;
|
||||||
efi_status_t ret;
|
efi_status_t ret;
|
||||||
|
|
||||||
/* Allow unaligned memory access */
|
|
||||||
allow_unaligned();
|
|
||||||
|
|
||||||
switch_to_non_secure_mode();
|
|
||||||
|
|
||||||
/* Initialize EFI drivers */
|
/* Initialize EFI drivers */
|
||||||
ret = efi_init_obj_list();
|
ret = efi_init_obj_list();
|
||||||
if (ret != EFI_SUCCESS) {
|
if (ret != EFI_SUCCESS) {
|
||||||
|
|
|
@ -128,7 +128,8 @@ struct efi_boot_services {
|
||||||
efi_status_t exit_status,
|
efi_status_t exit_status,
|
||||||
efi_uintn_t exitdata_size, u16 *exitdata);
|
efi_uintn_t exitdata_size, u16 *exitdata);
|
||||||
efi_status_t (EFIAPI *unload_image)(efi_handle_t image_handle);
|
efi_status_t (EFIAPI *unload_image)(efi_handle_t image_handle);
|
||||||
efi_status_t (EFIAPI *exit_boot_services)(efi_handle_t, unsigned long);
|
efi_status_t (EFIAPI *exit_boot_services)(efi_handle_t image_handle,
|
||||||
|
efi_uintn_t map_key);
|
||||||
|
|
||||||
efi_status_t (EFIAPI *get_next_monotonic_count)(u64 *count);
|
efi_status_t (EFIAPI *get_next_monotonic_count)(u64 *count);
|
||||||
efi_status_t (EFIAPI *stall)(unsigned long usecs);
|
efi_status_t (EFIAPI *stall)(unsigned long usecs);
|
||||||
|
@ -348,7 +349,7 @@ struct efi_loaded_image {
|
||||||
aligned_u64 image_size;
|
aligned_u64 image_size;
|
||||||
unsigned int image_code_type;
|
unsigned int image_code_type;
|
||||||
unsigned int image_data_type;
|
unsigned int image_data_type;
|
||||||
unsigned long unload;
|
efi_status_t (EFIAPI *unload)(efi_handle_t image_handle);
|
||||||
};
|
};
|
||||||
|
|
||||||
#define EFI_DEVICE_PATH_PROTOCOL_GUID \
|
#define EFI_DEVICE_PATH_PROTOCOL_GUID \
|
||||||
|
|
|
@ -179,6 +179,19 @@ struct efi_handler {
|
||||||
struct list_head open_infos;
|
struct list_head open_infos;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* enum efi_object_type - type of EFI object
|
||||||
|
*
|
||||||
|
* In UnloadImage we must be able to identify if the handle relates to a
|
||||||
|
* started image.
|
||||||
|
*/
|
||||||
|
enum efi_object_type {
|
||||||
|
EFI_OBJECT_TYPE_UNDEFINED = 0,
|
||||||
|
EFI_OBJECT_TYPE_U_BOOT_FIRMWARE,
|
||||||
|
EFI_OBJECT_TYPE_LOADED_IMAGE,
|
||||||
|
EFI_OBJECT_TYPE_STARTED_IMAGE,
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct efi_object - dereferenced EFI handle
|
* struct efi_object - dereferenced EFI handle
|
||||||
*
|
*
|
||||||
|
@ -201,6 +214,7 @@ struct efi_object {
|
||||||
struct list_head link;
|
struct list_head link;
|
||||||
/* The list of protocols */
|
/* The list of protocols */
|
||||||
struct list_head protocols;
|
struct list_head protocols;
|
||||||
|
enum efi_object_type type;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -221,6 +235,7 @@ struct efi_loaded_image_obj {
|
||||||
struct jmp_buf_data exit_jmp;
|
struct jmp_buf_data exit_jmp;
|
||||||
EFIAPI efi_status_t (*entry)(efi_handle_t image_handle,
|
EFIAPI efi_status_t (*entry)(efi_handle_t image_handle,
|
||||||
struct efi_system_table *st);
|
struct efi_system_table *st);
|
||||||
|
u16 image_type;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -257,6 +272,25 @@ extern struct list_head efi_obj_list;
|
||||||
/* List of all events */
|
/* List of all events */
|
||||||
extern struct list_head efi_events;
|
extern struct list_head efi_events;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* efi_register_notify_event - event registered by RegisterProtocolNotify()
|
||||||
|
*
|
||||||
|
* The address of this structure serves as registration value.
|
||||||
|
*
|
||||||
|
* @link: link to list of all registered events
|
||||||
|
* @event: registered event. The same event may registered for
|
||||||
|
* multiple GUIDs.
|
||||||
|
* @protocol: protocol for which the event is registered
|
||||||
|
*/
|
||||||
|
struct efi_register_notify_event {
|
||||||
|
struct list_head link;
|
||||||
|
struct efi_event *event;
|
||||||
|
efi_guid_t protocol;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* List of all events registered by RegisterProtocolNotify() */
|
||||||
|
extern struct list_head efi_register_notify_events;
|
||||||
|
|
||||||
/* Initialize efi execution environment */
|
/* Initialize efi execution environment */
|
||||||
efi_status_t efi_init_obj_list(void);
|
efi_status_t efi_init_obj_list(void);
|
||||||
/* Called by bootefi to initialize root node */
|
/* Called by bootefi to initialize root node */
|
||||||
|
|
|
@ -92,17 +92,6 @@ u16 *efi_st_translate_char(u16 code);
|
||||||
*/
|
*/
|
||||||
u16 *efi_st_translate_code(u16 code);
|
u16 *efi_st_translate_code(u16 code);
|
||||||
|
|
||||||
/*
|
|
||||||
* Compare memory.
|
|
||||||
* We cannot use lib/string.c due to different CFLAGS values.
|
|
||||||
*
|
|
||||||
* @buf1: first buffer
|
|
||||||
* @buf2: second buffer
|
|
||||||
* @length: number of bytes to compare
|
|
||||||
* @return: 0 if both buffers contain the same bytes
|
|
||||||
*/
|
|
||||||
int efi_st_memcmp(const void *buf1, const void *buf2, size_t length);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Compare an u16 string to a char string.
|
* Compare an u16 string to a char string.
|
||||||
*
|
*
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include <linux/libfdt_env.h>
|
#include <linux/libfdt_env.h>
|
||||||
#include <u-boot/crc.h>
|
#include <u-boot/crc.h>
|
||||||
#include <bootm.h>
|
#include <bootm.h>
|
||||||
|
#include <pe.h>
|
||||||
#include <watchdog.h>
|
#include <watchdog.h>
|
||||||
|
|
||||||
DECLARE_GLOBAL_DATA_PTR;
|
DECLARE_GLOBAL_DATA_PTR;
|
||||||
|
@ -26,6 +27,9 @@ LIST_HEAD(efi_obj_list);
|
||||||
/* List of all events */
|
/* List of all events */
|
||||||
LIST_HEAD(efi_events);
|
LIST_HEAD(efi_events);
|
||||||
|
|
||||||
|
/* List of all events registered by RegisterProtocolNotify() */
|
||||||
|
LIST_HEAD(efi_register_notify_events);
|
||||||
|
|
||||||
/* Handle of the currently executing image */
|
/* Handle of the currently executing image */
|
||||||
static efi_handle_t current_image;
|
static efi_handle_t current_image;
|
||||||
|
|
||||||
|
@ -238,7 +242,7 @@ void efi_signal_event(struct efi_event *event, bool check_tpl)
|
||||||
if (evt->is_queued)
|
if (evt->is_queued)
|
||||||
efi_queue_event(evt, check_tpl);
|
efi_queue_event(evt, check_tpl);
|
||||||
}
|
}
|
||||||
} else if (!event->is_signaled) {
|
} else {
|
||||||
event->is_signaled = true;
|
event->is_signaled = true;
|
||||||
if (event->type & EVT_NOTIFY_SIGNAL)
|
if (event->type & EVT_NOTIFY_SIGNAL)
|
||||||
efi_queue_event(event, check_tpl);
|
efi_queue_event(event, check_tpl);
|
||||||
|
@ -263,7 +267,7 @@ static unsigned long EFIAPI efi_raise_tpl(efi_uintn_t new_tpl)
|
||||||
EFI_ENTRY("0x%zx", new_tpl);
|
EFI_ENTRY("0x%zx", new_tpl);
|
||||||
|
|
||||||
if (new_tpl < efi_tpl)
|
if (new_tpl < efi_tpl)
|
||||||
debug("WARNING: new_tpl < current_tpl in %s\n", __func__);
|
EFI_PRINT("WARNING: new_tpl < current_tpl in %s\n", __func__);
|
||||||
efi_tpl = new_tpl;
|
efi_tpl = new_tpl;
|
||||||
if (efi_tpl > TPL_HIGH_LEVEL)
|
if (efi_tpl > TPL_HIGH_LEVEL)
|
||||||
efi_tpl = TPL_HIGH_LEVEL;
|
efi_tpl = TPL_HIGH_LEVEL;
|
||||||
|
@ -286,7 +290,7 @@ static void EFIAPI efi_restore_tpl(efi_uintn_t old_tpl)
|
||||||
EFI_ENTRY("0x%zx", old_tpl);
|
EFI_ENTRY("0x%zx", old_tpl);
|
||||||
|
|
||||||
if (old_tpl > efi_tpl)
|
if (old_tpl > efi_tpl)
|
||||||
debug("WARNING: old_tpl > current_tpl in %s\n", __func__);
|
EFI_PRINT("WARNING: old_tpl > current_tpl in %s\n", __func__);
|
||||||
efi_tpl = old_tpl;
|
efi_tpl = old_tpl;
|
||||||
if (efi_tpl > TPL_HIGH_LEVEL)
|
if (efi_tpl > TPL_HIGH_LEVEL)
|
||||||
efi_tpl = TPL_HIGH_LEVEL;
|
efi_tpl = TPL_HIGH_LEVEL;
|
||||||
|
@ -664,10 +668,26 @@ efi_status_t EFIAPI efi_create_event_ex(uint32_t type, efi_uintn_t notify_tpl,
|
||||||
efi_guid_t *event_group,
|
efi_guid_t *event_group,
|
||||||
struct efi_event **event)
|
struct efi_event **event)
|
||||||
{
|
{
|
||||||
|
efi_status_t ret;
|
||||||
|
|
||||||
EFI_ENTRY("%d, 0x%zx, %p, %p, %pUl", type, notify_tpl, notify_function,
|
EFI_ENTRY("%d, 0x%zx, %p, %p, %pUl", type, notify_tpl, notify_function,
|
||||||
notify_context, event_group);
|
notify_context, event_group);
|
||||||
return EFI_EXIT(efi_create_event(type, notify_tpl, notify_function,
|
|
||||||
notify_context, event_group, event));
|
/*
|
||||||
|
* The allowable input parameters are the same as in CreateEvent()
|
||||||
|
* except for the following two disallowed event types.
|
||||||
|
*/
|
||||||
|
switch (type) {
|
||||||
|
case EVT_SIGNAL_EXIT_BOOT_SERVICES:
|
||||||
|
case EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE:
|
||||||
|
ret = EFI_INVALID_PARAMETER;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = efi_create_event(type, notify_tpl, notify_function,
|
||||||
|
notify_context, event_group, event);
|
||||||
|
out:
|
||||||
|
return EFI_EXIT(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -891,9 +911,21 @@ static efi_status_t EFIAPI efi_signal_event_ext(struct efi_event *event)
|
||||||
*/
|
*/
|
||||||
static efi_status_t EFIAPI efi_close_event(struct efi_event *event)
|
static efi_status_t EFIAPI efi_close_event(struct efi_event *event)
|
||||||
{
|
{
|
||||||
|
struct efi_register_notify_event *item, *next;
|
||||||
|
|
||||||
EFI_ENTRY("%p", event);
|
EFI_ENTRY("%p", event);
|
||||||
if (efi_is_event(event) != EFI_SUCCESS)
|
if (efi_is_event(event) != EFI_SUCCESS)
|
||||||
return EFI_EXIT(EFI_INVALID_PARAMETER);
|
return EFI_EXIT(EFI_INVALID_PARAMETER);
|
||||||
|
|
||||||
|
/* Remove protocol notify registrations for the event */
|
||||||
|
list_for_each_entry_safe(item, next, &efi_register_notify_events,
|
||||||
|
link) {
|
||||||
|
if (event == item->event) {
|
||||||
|
list_del(&item->link);
|
||||||
|
free(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
list_del(&event->link);
|
list_del(&event->link);
|
||||||
free(event);
|
free(event);
|
||||||
return EFI_EXIT(EFI_SUCCESS);
|
return EFI_EXIT(EFI_SUCCESS);
|
||||||
|
@ -939,11 +971,13 @@ struct efi_object *efi_search_obj(const efi_handle_t handle)
|
||||||
{
|
{
|
||||||
struct efi_object *efiobj;
|
struct efi_object *efiobj;
|
||||||
|
|
||||||
|
if (!handle)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
list_for_each_entry(efiobj, &efi_obj_list, link) {
|
list_for_each_entry(efiobj, &efi_obj_list, link) {
|
||||||
if (efiobj == handle)
|
if (efiobj == handle)
|
||||||
return efiobj;
|
return efiobj;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -997,6 +1031,7 @@ efi_status_t efi_add_protocol(const efi_handle_t handle,
|
||||||
struct efi_object *efiobj;
|
struct efi_object *efiobj;
|
||||||
struct efi_handler *handler;
|
struct efi_handler *handler;
|
||||||
efi_status_t ret;
|
efi_status_t ret;
|
||||||
|
struct efi_register_notify_event *event;
|
||||||
|
|
||||||
efiobj = efi_search_obj(handle);
|
efiobj = efi_search_obj(handle);
|
||||||
if (!efiobj)
|
if (!efiobj)
|
||||||
|
@ -1011,6 +1046,13 @@ efi_status_t efi_add_protocol(const efi_handle_t handle,
|
||||||
handler->protocol_interface = protocol_interface;
|
handler->protocol_interface = protocol_interface;
|
||||||
INIT_LIST_HEAD(&handler->open_infos);
|
INIT_LIST_HEAD(&handler->open_infos);
|
||||||
list_add_tail(&handler->link, &efiobj->protocols);
|
list_add_tail(&handler->link, &efiobj->protocols);
|
||||||
|
|
||||||
|
/* Notify registered events */
|
||||||
|
list_for_each_entry(event, &efi_register_notify_events, link) {
|
||||||
|
if (!guidcmp(protocol, &event->protocol))
|
||||||
|
efi_signal_event(event->event, true);
|
||||||
|
}
|
||||||
|
|
||||||
if (!guidcmp(&efi_guid_device_path, protocol))
|
if (!guidcmp(&efi_guid_device_path, protocol))
|
||||||
EFI_PRINT("installed device path '%pD'\n", protocol_interface);
|
EFI_PRINT("installed device path '%pD'\n", protocol_interface);
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
|
@ -1051,11 +1093,9 @@ static efi_status_t EFIAPI efi_install_protocol_interface(
|
||||||
r = efi_create_handle(handle);
|
r = efi_create_handle(handle);
|
||||||
if (r != EFI_SUCCESS)
|
if (r != EFI_SUCCESS)
|
||||||
goto out;
|
goto out;
|
||||||
debug("%sEFI: new handle %p\n", indent_string(nesting_level),
|
EFI_PRINT("new handle %p\n", *handle);
|
||||||
*handle);
|
|
||||||
} else {
|
} else {
|
||||||
debug("%sEFI: handle %p\n", indent_string(nesting_level),
|
EFI_PRINT("handle %p\n", *handle);
|
||||||
*handle);
|
|
||||||
}
|
}
|
||||||
/* Add new protocol */
|
/* Add new protocol */
|
||||||
r = efi_add_protocol(*handle, protocol, protocol_interface);
|
r = efi_add_protocol(*handle, protocol, protocol_interface);
|
||||||
|
@ -1274,8 +1314,30 @@ static efi_status_t EFIAPI efi_register_protocol_notify(
|
||||||
struct efi_event *event,
|
struct efi_event *event,
|
||||||
void **registration)
|
void **registration)
|
||||||
{
|
{
|
||||||
|
struct efi_register_notify_event *item;
|
||||||
|
efi_status_t ret = EFI_SUCCESS;
|
||||||
|
|
||||||
EFI_ENTRY("%pUl, %p, %p", protocol, event, registration);
|
EFI_ENTRY("%pUl, %p, %p", protocol, event, registration);
|
||||||
return EFI_EXIT(EFI_OUT_OF_RESOURCES);
|
|
||||||
|
if (!protocol || !event || !registration) {
|
||||||
|
ret = EFI_INVALID_PARAMETER;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
item = calloc(1, sizeof(struct efi_register_notify_event));
|
||||||
|
if (!item) {
|
||||||
|
ret = EFI_OUT_OF_RESOURCES;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
item->event = event;
|
||||||
|
memcpy(&item->protocol, protocol, sizeof(efi_guid_t));
|
||||||
|
|
||||||
|
list_add_tail(&item->link, &efi_register_notify_events);
|
||||||
|
|
||||||
|
*registration = item;
|
||||||
|
out:
|
||||||
|
return EFI_EXIT(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1290,8 +1352,7 @@ static efi_status_t EFIAPI efi_register_protocol_notify(
|
||||||
* Return: 0 if the handle implements the protocol
|
* Return: 0 if the handle implements the protocol
|
||||||
*/
|
*/
|
||||||
static int efi_search(enum efi_locate_search_type search_type,
|
static int efi_search(enum efi_locate_search_type search_type,
|
||||||
const efi_guid_t *protocol, void *search_key,
|
const efi_guid_t *protocol, efi_handle_t handle)
|
||||||
efi_handle_t handle)
|
|
||||||
{
|
{
|
||||||
efi_status_t ret;
|
efi_status_t ret;
|
||||||
|
|
||||||
|
@ -1299,8 +1360,6 @@ static int efi_search(enum efi_locate_search_type search_type,
|
||||||
case ALL_HANDLES:
|
case ALL_HANDLES:
|
||||||
return 0;
|
return 0;
|
||||||
case BY_REGISTER_NOTIFY:
|
case BY_REGISTER_NOTIFY:
|
||||||
/* TODO: RegisterProtocolNotify is not implemented yet */
|
|
||||||
return -1;
|
|
||||||
case BY_PROTOCOL:
|
case BY_PROTOCOL:
|
||||||
ret = efi_search_protocol(handle, protocol, NULL);
|
ret = efi_search_protocol(handle, protocol, NULL);
|
||||||
return (ret != EFI_SUCCESS);
|
return (ret != EFI_SUCCESS);
|
||||||
|
@ -1312,11 +1371,12 @@ static int efi_search(enum efi_locate_search_type search_type,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* efi_locate_handle() - locate handles implementing a protocol
|
* efi_locate_handle() - locate handles implementing a protocol
|
||||||
* @search_type: selection criterion
|
*
|
||||||
* @protocol: GUID of the protocol
|
* @search_type: selection criterion
|
||||||
* @search_key: registration key
|
* @protocol: GUID of the protocol
|
||||||
* @buffer_size: size of the buffer to receive the handles in bytes
|
* @search_key: registration key
|
||||||
* @buffer: buffer to receive the relevant handles
|
* @buffer_size: size of the buffer to receive the handles in bytes
|
||||||
|
* @buffer: buffer to receive the relevant handles
|
||||||
*
|
*
|
||||||
* This function is meant for U-Boot internal calls. For the API implementation
|
* This function is meant for U-Boot internal calls. For the API implementation
|
||||||
* of the LocateHandle service see efi_locate_handle_ext.
|
* of the LocateHandle service see efi_locate_handle_ext.
|
||||||
|
@ -1330,6 +1390,7 @@ static efi_status_t efi_locate_handle(
|
||||||
{
|
{
|
||||||
struct efi_object *efiobj;
|
struct efi_object *efiobj;
|
||||||
efi_uintn_t size = 0;
|
efi_uintn_t size = 0;
|
||||||
|
struct efi_register_notify_event *item, *event = NULL;
|
||||||
|
|
||||||
/* Check parameters */
|
/* Check parameters */
|
||||||
switch (search_type) {
|
switch (search_type) {
|
||||||
|
@ -1338,8 +1399,19 @@ static efi_status_t efi_locate_handle(
|
||||||
case BY_REGISTER_NOTIFY:
|
case BY_REGISTER_NOTIFY:
|
||||||
if (!search_key)
|
if (!search_key)
|
||||||
return EFI_INVALID_PARAMETER;
|
return EFI_INVALID_PARAMETER;
|
||||||
/* RegisterProtocolNotify is not implemented yet */
|
/* Check that the registration key is valid */
|
||||||
return EFI_UNSUPPORTED;
|
list_for_each_entry(item, &efi_register_notify_events, link) {
|
||||||
|
if (item ==
|
||||||
|
(struct efi_register_notify_event *)search_key) {
|
||||||
|
event = item;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!event)
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
protocol = &event->protocol;
|
||||||
|
break;
|
||||||
case BY_PROTOCOL:
|
case BY_PROTOCOL:
|
||||||
if (!protocol)
|
if (!protocol)
|
||||||
return EFI_INVALID_PARAMETER;
|
return EFI_INVALID_PARAMETER;
|
||||||
|
@ -1348,32 +1420,32 @@ static efi_status_t efi_locate_handle(
|
||||||
return EFI_INVALID_PARAMETER;
|
return EFI_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* efi_locate_handle_buffer uses this function for
|
|
||||||
* the calculation of the necessary buffer size.
|
|
||||||
* So do not require a buffer for buffersize == 0.
|
|
||||||
*/
|
|
||||||
if (!buffer_size || (*buffer_size && !buffer))
|
|
||||||
return EFI_INVALID_PARAMETER;
|
|
||||||
|
|
||||||
/* Count how much space we need */
|
/* Count how much space we need */
|
||||||
list_for_each_entry(efiobj, &efi_obj_list, link) {
|
list_for_each_entry(efiobj, &efi_obj_list, link) {
|
||||||
if (!efi_search(search_type, protocol, search_key, efiobj))
|
if (!efi_search(search_type, protocol, efiobj))
|
||||||
size += sizeof(void *);
|
size += sizeof(void *);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (size == 0)
|
||||||
|
return EFI_NOT_FOUND;
|
||||||
|
|
||||||
|
if (!buffer_size)
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
|
||||||
if (*buffer_size < size) {
|
if (*buffer_size < size) {
|
||||||
*buffer_size = size;
|
*buffer_size = size;
|
||||||
return EFI_BUFFER_TOO_SMALL;
|
return EFI_BUFFER_TOO_SMALL;
|
||||||
}
|
}
|
||||||
|
|
||||||
*buffer_size = size;
|
*buffer_size = size;
|
||||||
if (size == 0)
|
|
||||||
return EFI_NOT_FOUND;
|
/* The buffer size is sufficient but there is not buffer */
|
||||||
|
if (!buffer)
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
|
||||||
/* Then fill the array */
|
/* Then fill the array */
|
||||||
list_for_each_entry(efiobj, &efi_obj_list, link) {
|
list_for_each_entry(efiobj, &efi_obj_list, link) {
|
||||||
if (!efi_search(search_type, protocol, search_key, efiobj))
|
if (!efi_search(search_type, protocol, efiobj))
|
||||||
*buffer++ = efiobj;
|
*buffer++ = efiobj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1538,6 +1610,7 @@ efi_status_t efi_setup_loaded_image(struct efi_device_path *device_path,
|
||||||
free(info);
|
free(info);
|
||||||
return EFI_OUT_OF_RESOURCES;
|
return EFI_OUT_OF_RESOURCES;
|
||||||
}
|
}
|
||||||
|
obj->header.type = EFI_OBJECT_TYPE_LOADED_IMAGE;
|
||||||
|
|
||||||
/* Add internal object to object list */
|
/* Add internal object to object list */
|
||||||
efi_add_handle(&obj->header);
|
efi_add_handle(&obj->header);
|
||||||
|
@ -1687,7 +1760,7 @@ efi_status_t EFIAPI efi_load_image(bool boot_policy,
|
||||||
EFI_ENTRY("%d, %p, %pD, %p, %zd, %p", boot_policy, parent_image,
|
EFI_ENTRY("%d, %p, %pD, %p, %zd, %p", boot_policy, parent_image,
|
||||||
file_path, source_buffer, source_size, image_handle);
|
file_path, source_buffer, source_size, image_handle);
|
||||||
|
|
||||||
if (!image_handle || !parent_image) {
|
if (!image_handle || !efi_search_obj(parent_image)) {
|
||||||
ret = EFI_INVALID_PARAMETER;
|
ret = EFI_INVALID_PARAMETER;
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
@ -1696,6 +1769,11 @@ efi_status_t EFIAPI efi_load_image(bool boot_policy,
|
||||||
ret = EFI_NOT_FOUND;
|
ret = EFI_NOT_FOUND;
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
/* The parent image handle must refer to a loaded image */
|
||||||
|
if (!parent_image->type) {
|
||||||
|
ret = EFI_INVALID_PARAMETER;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
if (!source_buffer) {
|
if (!source_buffer) {
|
||||||
ret = efi_load_image_from_path(file_path, &dest_buffer,
|
ret = efi_load_image_from_path(file_path, &dest_buffer,
|
||||||
|
@ -1703,6 +1781,10 @@ efi_status_t EFIAPI efi_load_image(bool boot_policy,
|
||||||
if (ret != EFI_SUCCESS)
|
if (ret != EFI_SUCCESS)
|
||||||
goto error;
|
goto error;
|
||||||
} else {
|
} else {
|
||||||
|
if (!source_size) {
|
||||||
|
ret = EFI_LOAD_ERROR;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
dest_buffer = source_buffer;
|
dest_buffer = source_buffer;
|
||||||
}
|
}
|
||||||
/* split file_path which contains both the device and file parts */
|
/* split file_path which contains both the device and file parts */
|
||||||
|
@ -1727,29 +1809,6 @@ error:
|
||||||
return EFI_EXIT(ret);
|
return EFI_EXIT(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* efi_unload_image() - unload an EFI image
|
|
||||||
* @image_handle: handle of the image to be unloaded
|
|
||||||
*
|
|
||||||
* This function implements the UnloadImage service.
|
|
||||||
*
|
|
||||||
* See the Unified Extensible Firmware Interface (UEFI) specification for
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* Return: status code
|
|
||||||
*/
|
|
||||||
efi_status_t EFIAPI efi_unload_image(efi_handle_t image_handle)
|
|
||||||
{
|
|
||||||
struct efi_object *efiobj;
|
|
||||||
|
|
||||||
EFI_ENTRY("%p", image_handle);
|
|
||||||
efiobj = efi_search_obj(image_handle);
|
|
||||||
if (efiobj)
|
|
||||||
list_del(&efiobj->link);
|
|
||||||
|
|
||||||
return EFI_EXIT(EFI_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* efi_exit_caches() - fix up caches for EFI payloads if necessary
|
* efi_exit_caches() - fix up caches for EFI payloads if necessary
|
||||||
*/
|
*/
|
||||||
|
@ -1782,11 +1841,11 @@ static void efi_exit_caches(void)
|
||||||
* Return: status code
|
* Return: status code
|
||||||
*/
|
*/
|
||||||
static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle,
|
static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle,
|
||||||
unsigned long map_key)
|
efi_uintn_t map_key)
|
||||||
{
|
{
|
||||||
struct efi_event *evt;
|
struct efi_event *evt;
|
||||||
|
|
||||||
EFI_ENTRY("%p, %ld", image_handle, map_key);
|
EFI_ENTRY("%p, %zx", image_handle, map_key);
|
||||||
|
|
||||||
/* Check that the caller has read the current memory map */
|
/* Check that the caller has read the current memory map */
|
||||||
if (map_key != efi_memory_map_key)
|
if (map_key != efi_memory_map_key)
|
||||||
|
@ -1932,7 +1991,8 @@ static efi_status_t EFIAPI efi_close_protocol(efi_handle_t handle,
|
||||||
EFI_ENTRY("%p, %pUl, %p, %p", handle, protocol, agent_handle,
|
EFI_ENTRY("%p, %pUl, %p, %p", handle, protocol, agent_handle,
|
||||||
controller_handle);
|
controller_handle);
|
||||||
|
|
||||||
if (!agent_handle) {
|
if (!efi_search_obj(agent_handle) ||
|
||||||
|
(controller_handle && !efi_search_obj(controller_handle))) {
|
||||||
r = EFI_INVALID_PARAMETER;
|
r = EFI_INVALID_PARAMETER;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -2585,8 +2645,15 @@ static efi_status_t EFIAPI efi_open_protocol
|
||||||
}
|
}
|
||||||
|
|
||||||
r = efi_search_protocol(handle, protocol, &handler);
|
r = efi_search_protocol(handle, protocol, &handler);
|
||||||
if (r != EFI_SUCCESS)
|
switch (r) {
|
||||||
|
case EFI_SUCCESS:
|
||||||
|
break;
|
||||||
|
case EFI_NOT_FOUND:
|
||||||
|
r = EFI_UNSUPPORTED;
|
||||||
goto out;
|
goto out;
|
||||||
|
default:
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
r = efi_protocol_open(handler, protocol_interface, agent_handle,
|
r = efi_protocol_open(handler, protocol_interface, agent_handle,
|
||||||
controller_handle, attributes);
|
controller_handle, attributes);
|
||||||
|
@ -2653,15 +2720,15 @@ efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle,
|
||||||
* missed out steps of EFI_CALL.
|
* missed out steps of EFI_CALL.
|
||||||
*/
|
*/
|
||||||
assert(__efi_entry_check());
|
assert(__efi_entry_check());
|
||||||
debug("%sEFI: %lu returned by started image\n",
|
EFI_PRINT("%lu returned by started image\n",
|
||||||
__efi_nesting_dec(),
|
(unsigned long)((uintptr_t)image_obj->exit_status &
|
||||||
(unsigned long)((uintptr_t)image_obj->exit_status &
|
~EFI_ERROR_MASK));
|
||||||
~EFI_ERROR_MASK));
|
|
||||||
current_image = parent_image;
|
current_image = parent_image;
|
||||||
return EFI_EXIT(image_obj->exit_status);
|
return EFI_EXIT(image_obj->exit_status);
|
||||||
}
|
}
|
||||||
|
|
||||||
current_image = image_handle;
|
current_image = image_handle;
|
||||||
|
image_obj->header.type = EFI_OBJECT_TYPE_STARTED_IMAGE;
|
||||||
EFI_PRINT("Jumping into 0x%p\n", image_obj->entry);
|
EFI_PRINT("Jumping into 0x%p\n", image_obj->entry);
|
||||||
ret = EFI_CALL(image_obj->entry(image_handle, &systab));
|
ret = EFI_CALL(image_obj->entry(image_handle, &systab));
|
||||||
|
|
||||||
|
@ -2674,6 +2741,76 @@ efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle,
|
||||||
return EFI_CALL(systab.boottime->exit(image_handle, ret, 0, NULL));
|
return EFI_CALL(systab.boottime->exit(image_handle, ret, 0, NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* efi_delete_image() - delete loaded image from memory)
|
||||||
|
*
|
||||||
|
* @image_obj: handle of the loaded image
|
||||||
|
* @loaded_image_protocol: loaded image protocol
|
||||||
|
*/
|
||||||
|
static void efi_delete_image(struct efi_loaded_image_obj *image_obj,
|
||||||
|
struct efi_loaded_image *loaded_image_protocol)
|
||||||
|
{
|
||||||
|
efi_free_pages((uintptr_t)loaded_image_protocol->image_base,
|
||||||
|
efi_size_in_pages(loaded_image_protocol->image_size));
|
||||||
|
efi_delete_handle(&image_obj->header);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* efi_unload_image() - unload an EFI image
|
||||||
|
* @image_handle: handle of the image to be unloaded
|
||||||
|
*
|
||||||
|
* This function implements the UnloadImage service.
|
||||||
|
*
|
||||||
|
* See the Unified Extensible Firmware Interface (UEFI) specification for
|
||||||
|
* details.
|
||||||
|
*
|
||||||
|
* Return: status code
|
||||||
|
*/
|
||||||
|
efi_status_t EFIAPI efi_unload_image(efi_handle_t image_handle)
|
||||||
|
{
|
||||||
|
efi_status_t ret = EFI_SUCCESS;
|
||||||
|
struct efi_object *efiobj;
|
||||||
|
struct efi_loaded_image *loaded_image_protocol;
|
||||||
|
|
||||||
|
EFI_ENTRY("%p", image_handle);
|
||||||
|
|
||||||
|
efiobj = efi_search_obj(image_handle);
|
||||||
|
if (!efiobj) {
|
||||||
|
ret = EFI_INVALID_PARAMETER;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
/* Find the loaded image protocol */
|
||||||
|
ret = EFI_CALL(efi_open_protocol(image_handle, &efi_guid_loaded_image,
|
||||||
|
(void **)&loaded_image_protocol,
|
||||||
|
NULL, NULL,
|
||||||
|
EFI_OPEN_PROTOCOL_GET_PROTOCOL));
|
||||||
|
if (ret != EFI_SUCCESS) {
|
||||||
|
ret = EFI_INVALID_PARAMETER;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
switch (efiobj->type) {
|
||||||
|
case EFI_OBJECT_TYPE_STARTED_IMAGE:
|
||||||
|
/* Call the unload function */
|
||||||
|
if (!loaded_image_protocol->unload) {
|
||||||
|
ret = EFI_UNSUPPORTED;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
ret = EFI_CALL(loaded_image_protocol->unload(image_handle));
|
||||||
|
if (ret != EFI_SUCCESS)
|
||||||
|
goto out;
|
||||||
|
break;
|
||||||
|
case EFI_OBJECT_TYPE_LOADED_IMAGE:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ret = EFI_INVALID_PARAMETER;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
efi_delete_image((struct efi_loaded_image_obj *)efiobj,
|
||||||
|
loaded_image_protocol);
|
||||||
|
out:
|
||||||
|
return EFI_EXIT(ret);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* efi_update_exit_data() - fill exit data parameters of StartImage()
|
* efi_update_exit_data() - fill exit data parameters of StartImage()
|
||||||
*
|
*
|
||||||
|
@ -2733,7 +2870,7 @@ static efi_status_t EFIAPI efi_exit(efi_handle_t image_handle,
|
||||||
* image protocol.
|
* image protocol.
|
||||||
*/
|
*/
|
||||||
efi_status_t ret;
|
efi_status_t ret;
|
||||||
void *info;
|
struct efi_loaded_image *loaded_image_protocol;
|
||||||
struct efi_loaded_image_obj *image_obj =
|
struct efi_loaded_image_obj *image_obj =
|
||||||
(struct efi_loaded_image_obj *)image_handle;
|
(struct efi_loaded_image_obj *)image_handle;
|
||||||
|
|
||||||
|
@ -2741,13 +2878,33 @@ static efi_status_t EFIAPI efi_exit(efi_handle_t image_handle,
|
||||||
exit_data_size, exit_data);
|
exit_data_size, exit_data);
|
||||||
|
|
||||||
/* Check parameters */
|
/* Check parameters */
|
||||||
if (image_handle != current_image)
|
|
||||||
goto out;
|
|
||||||
ret = EFI_CALL(efi_open_protocol(image_handle, &efi_guid_loaded_image,
|
ret = EFI_CALL(efi_open_protocol(image_handle, &efi_guid_loaded_image,
|
||||||
&info, NULL, NULL,
|
(void **)&loaded_image_protocol,
|
||||||
|
NULL, NULL,
|
||||||
EFI_OPEN_PROTOCOL_GET_PROTOCOL));
|
EFI_OPEN_PROTOCOL_GET_PROTOCOL));
|
||||||
if (ret != EFI_SUCCESS)
|
if (ret != EFI_SUCCESS) {
|
||||||
|
ret = EFI_INVALID_PARAMETER;
|
||||||
goto out;
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Unloading of unstarted images */
|
||||||
|
switch (image_obj->header.type) {
|
||||||
|
case EFI_OBJECT_TYPE_STARTED_IMAGE:
|
||||||
|
break;
|
||||||
|
case EFI_OBJECT_TYPE_LOADED_IMAGE:
|
||||||
|
efi_delete_image(image_obj, loaded_image_protocol);
|
||||||
|
ret = EFI_SUCCESS;
|
||||||
|
goto out;
|
||||||
|
default:
|
||||||
|
/* Handle does not refer to loaded image */
|
||||||
|
ret = EFI_INVALID_PARAMETER;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
/* A started image can only be unloaded it is the last one started. */
|
||||||
|
if (image_handle != current_image) {
|
||||||
|
ret = EFI_INVALID_PARAMETER;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
/* Exit data is only foreseen in case of failure. */
|
/* Exit data is only foreseen in case of failure. */
|
||||||
if (exit_status != EFI_SUCCESS) {
|
if (exit_status != EFI_SUCCESS) {
|
||||||
|
@ -2757,6 +2914,9 @@ static efi_status_t EFIAPI efi_exit(efi_handle_t image_handle,
|
||||||
if (ret != EFI_SUCCESS)
|
if (ret != EFI_SUCCESS)
|
||||||
EFI_PRINT("%s: out of memory\n", __func__);
|
EFI_PRINT("%s: out of memory\n", __func__);
|
||||||
}
|
}
|
||||||
|
if (image_obj->image_type == IMAGE_SUBSYSTEM_EFI_APPLICATION ||
|
||||||
|
exit_status != EFI_SUCCESS)
|
||||||
|
efi_delete_image(image_obj, loaded_image_protocol);
|
||||||
|
|
||||||
/* Make sure entry/exit counts for EFI world cross-overs match */
|
/* Make sure entry/exit counts for EFI world cross-overs match */
|
||||||
EFI_EXIT(exit_status);
|
EFI_EXIT(exit_status);
|
||||||
|
@ -2772,7 +2932,7 @@ static efi_status_t EFIAPI efi_exit(efi_handle_t image_handle,
|
||||||
|
|
||||||
panic("EFI application exited");
|
panic("EFI application exited");
|
||||||
out:
|
out:
|
||||||
return EFI_EXIT(EFI_INVALID_PARAMETER);
|
return EFI_EXIT(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -273,6 +273,7 @@ efi_status_t efi_load_pe(struct efi_loaded_image_obj *handle, void *efi,
|
||||||
IMAGE_OPTIONAL_HEADER64 *opt = &nt64->OptionalHeader;
|
IMAGE_OPTIONAL_HEADER64 *opt = &nt64->OptionalHeader;
|
||||||
image_base = opt->ImageBase;
|
image_base = opt->ImageBase;
|
||||||
efi_set_code_and_data_type(loaded_image_info, opt->Subsystem);
|
efi_set_code_and_data_type(loaded_image_info, opt->Subsystem);
|
||||||
|
handle->image_type = opt->Subsystem;
|
||||||
efi_reloc = efi_alloc(virt_size,
|
efi_reloc = efi_alloc(virt_size,
|
||||||
loaded_image_info->image_code_type);
|
loaded_image_info->image_code_type);
|
||||||
if (!efi_reloc) {
|
if (!efi_reloc) {
|
||||||
|
@ -288,6 +289,7 @@ efi_status_t efi_load_pe(struct efi_loaded_image_obj *handle, void *efi,
|
||||||
IMAGE_OPTIONAL_HEADER32 *opt = &nt->OptionalHeader;
|
IMAGE_OPTIONAL_HEADER32 *opt = &nt->OptionalHeader;
|
||||||
image_base = opt->ImageBase;
|
image_base = opt->ImageBase;
|
||||||
efi_set_code_and_data_type(loaded_image_info, opt->Subsystem);
|
efi_set_code_and_data_type(loaded_image_info, opt->Subsystem);
|
||||||
|
handle->image_type = opt->Subsystem;
|
||||||
efi_reloc = efi_alloc(virt_size,
|
efi_reloc = efi_alloc(virt_size,
|
||||||
loaded_image_info->image_code_type);
|
loaded_image_info->image_code_type);
|
||||||
if (!efi_reloc) {
|
if (!efi_reloc) {
|
||||||
|
|
|
@ -28,6 +28,7 @@ struct efi_root_dp {
|
||||||
*/
|
*/
|
||||||
efi_status_t efi_root_node_register(void)
|
efi_status_t efi_root_node_register(void)
|
||||||
{
|
{
|
||||||
|
efi_status_t ret;
|
||||||
struct efi_root_dp *dp;
|
struct efi_root_dp *dp;
|
||||||
|
|
||||||
/* Create device path protocol */
|
/* Create device path protocol */
|
||||||
|
@ -47,28 +48,31 @@ efi_status_t efi_root_node_register(void)
|
||||||
dp->end.length = sizeof(struct efi_device_path);
|
dp->end.length = sizeof(struct efi_device_path);
|
||||||
|
|
||||||
/* Create root node and install protocols */
|
/* Create root node and install protocols */
|
||||||
return EFI_CALL(efi_install_multiple_protocol_interfaces(&efi_root,
|
ret = EFI_CALL(efi_install_multiple_protocol_interfaces
|
||||||
/* Device path protocol */
|
(&efi_root,
|
||||||
&efi_guid_device_path, dp,
|
/* Device path protocol */
|
||||||
/* Device path to text protocol */
|
&efi_guid_device_path, dp,
|
||||||
&efi_guid_device_path_to_text_protocol,
|
/* Device path to text protocol */
|
||||||
(void *)&efi_device_path_to_text,
|
&efi_guid_device_path_to_text_protocol,
|
||||||
/* Device path utilities protocol */
|
(void *)&efi_device_path_to_text,
|
||||||
&efi_guid_device_path_utilities_protocol,
|
/* Device path utilities protocol */
|
||||||
(void *)&efi_device_path_utilities,
|
&efi_guid_device_path_utilities_protocol,
|
||||||
/* Unicode collation protocol */
|
(void *)&efi_device_path_utilities,
|
||||||
&efi_guid_unicode_collation_protocol,
|
/* Unicode collation protocol */
|
||||||
(void *)&efi_unicode_collation_protocol,
|
&efi_guid_unicode_collation_protocol,
|
||||||
|
(void *)&efi_unicode_collation_protocol,
|
||||||
#if CONFIG_IS_ENABLED(EFI_LOADER_HII)
|
#if CONFIG_IS_ENABLED(EFI_LOADER_HII)
|
||||||
/* HII string protocol */
|
/* HII string protocol */
|
||||||
&efi_guid_hii_string_protocol,
|
&efi_guid_hii_string_protocol,
|
||||||
(void *)&efi_hii_string,
|
(void *)&efi_hii_string,
|
||||||
/* HII database protocol */
|
/* HII database protocol */
|
||||||
&efi_guid_hii_database_protocol,
|
&efi_guid_hii_database_protocol,
|
||||||
(void *)&efi_hii_database,
|
(void *)&efi_hii_database,
|
||||||
/* HII configuration routing protocol */
|
/* HII configuration routing protocol */
|
||||||
&efi_guid_hii_config_routing_protocol,
|
&efi_guid_hii_config_routing_protocol,
|
||||||
(void *)&efi_hii_config_routing,
|
(void *)&efi_hii_config_routing,
|
||||||
#endif
|
#endif
|
||||||
NULL));
|
NULL));
|
||||||
|
efi_root->type = EFI_OBJECT_TYPE_U_BOOT_FIRMWARE;
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,12 +6,22 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <common.h>
|
#include <common.h>
|
||||||
|
#include <bootm.h>
|
||||||
#include <efi_loader.h>
|
#include <efi_loader.h>
|
||||||
|
|
||||||
#define OBJ_LIST_NOT_INITIALIZED 1
|
#define OBJ_LIST_NOT_INITIALIZED 1
|
||||||
|
|
||||||
static efi_status_t efi_obj_list_initialized = OBJ_LIST_NOT_INITIALIZED;
|
static efi_status_t efi_obj_list_initialized = OBJ_LIST_NOT_INITIALIZED;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allow unaligned memory access.
|
||||||
|
*
|
||||||
|
* This routine is overridden by architectures providing this feature.
|
||||||
|
*/
|
||||||
|
void __weak allow_unaligned(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* efi_init_platform_lang() - define supported languages
|
* efi_init_platform_lang() - define supported languages
|
||||||
*
|
*
|
||||||
|
@ -86,6 +96,12 @@ efi_status_t efi_init_obj_list(void)
|
||||||
if (efi_obj_list_initialized != OBJ_LIST_NOT_INITIALIZED)
|
if (efi_obj_list_initialized != OBJ_LIST_NOT_INITIALIZED)
|
||||||
return efi_obj_list_initialized;
|
return efi_obj_list_initialized;
|
||||||
|
|
||||||
|
/* Allow unaligned memory access */
|
||||||
|
allow_unaligned();
|
||||||
|
|
||||||
|
/* On ARM switch from EL3 or secure mode to EL2 or non-secure mode */
|
||||||
|
switch_to_non_secure_mode();
|
||||||
|
|
||||||
/* Define supported languages */
|
/* Define supported languages */
|
||||||
ret = efi_init_platform_lang();
|
ret = efi_init_platform_lang();
|
||||||
if (ret != EFI_SUCCESS)
|
if (ret != EFI_SUCCESS)
|
||||||
|
|
|
@ -27,6 +27,7 @@ efi_selftest_gop.o \
|
||||||
efi_selftest_loaded_image.o \
|
efi_selftest_loaded_image.o \
|
||||||
efi_selftest_manageprotocols.o \
|
efi_selftest_manageprotocols.o \
|
||||||
efi_selftest_memory.o \
|
efi_selftest_memory.o \
|
||||||
|
efi_selftest_register_notify.o \
|
||||||
efi_selftest_rtc.o \
|
efi_selftest_rtc.o \
|
||||||
efi_selftest_snp.o \
|
efi_selftest_snp.o \
|
||||||
efi_selftest_textinput.o \
|
efi_selftest_textinput.o \
|
||||||
|
|
|
@ -337,7 +337,7 @@ static int execute(void)
|
||||||
}
|
}
|
||||||
if (len >= dp_size(dp_partition))
|
if (len >= dp_size(dp_partition))
|
||||||
continue;
|
continue;
|
||||||
if (efi_st_memcmp(dp, dp_partition, len))
|
if (memcmp(dp, dp_partition, len))
|
||||||
continue;
|
continue;
|
||||||
handle_partition = handles[i];
|
handle_partition = handles[i];
|
||||||
break;
|
break;
|
||||||
|
@ -409,7 +409,7 @@ static int execute(void)
|
||||||
(unsigned int)buf_size);
|
(unsigned int)buf_size);
|
||||||
return EFI_ST_FAILURE;
|
return EFI_ST_FAILURE;
|
||||||
}
|
}
|
||||||
if (efi_st_memcmp(buf, "ello world!", 11)) {
|
if (memcmp(buf, "ello world!", 11)) {
|
||||||
efi_st_error("Unexpected file content\n");
|
efi_st_error("Unexpected file content\n");
|
||||||
return EFI_ST_FAILURE;
|
return EFI_ST_FAILURE;
|
||||||
}
|
}
|
||||||
|
@ -480,7 +480,7 @@ static int execute(void)
|
||||||
(unsigned int)buf_size);
|
(unsigned int)buf_size);
|
||||||
return EFI_ST_FAILURE;
|
return EFI_ST_FAILURE;
|
||||||
}
|
}
|
||||||
if (efi_st_memcmp(buf, "U-Boot", 7)) {
|
if (memcmp(buf, "U-Boot", 7)) {
|
||||||
efi_st_error("Unexpected file content %s\n", buf);
|
efi_st_error("Unexpected file content %s\n", buf);
|
||||||
return EFI_ST_FAILURE;
|
return EFI_ST_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -153,8 +153,8 @@ static int execute(void)
|
||||||
}
|
}
|
||||||
table = NULL;
|
table = NULL;
|
||||||
for (i = 0; i < sys_table->nr_tables; ++i) {
|
for (i = 0; i < sys_table->nr_tables; ++i) {
|
||||||
if (!efi_st_memcmp(&sys_table->tables[i].guid, &table_guid,
|
if (!memcmp(&sys_table->tables[i].guid, &table_guid,
|
||||||
sizeof(efi_guid_t)))
|
sizeof(efi_guid_t)))
|
||||||
table = sys_table->tables[i].table;
|
table = sys_table->tables[i].table;
|
||||||
}
|
}
|
||||||
if (!table) {
|
if (!table) {
|
||||||
|
@ -192,8 +192,8 @@ static int execute(void)
|
||||||
table = NULL;
|
table = NULL;
|
||||||
tabcnt = 0;
|
tabcnt = 0;
|
||||||
for (i = 0; i < sys_table->nr_tables; ++i) {
|
for (i = 0; i < sys_table->nr_tables; ++i) {
|
||||||
if (!efi_st_memcmp(&sys_table->tables[i].guid, &table_guid,
|
if (!memcmp(&sys_table->tables[i].guid, &table_guid,
|
||||||
sizeof(efi_guid_t))) {
|
sizeof(efi_guid_t))) {
|
||||||
table = sys_table->tables[i].table;
|
table = sys_table->tables[i].table;
|
||||||
++tabcnt;
|
++tabcnt;
|
||||||
}
|
}
|
||||||
|
@ -235,8 +235,8 @@ static int execute(void)
|
||||||
}
|
}
|
||||||
table = NULL;
|
table = NULL;
|
||||||
for (i = 0; i < sys_table->nr_tables; ++i) {
|
for (i = 0; i < sys_table->nr_tables; ++i) {
|
||||||
if (!efi_st_memcmp(&sys_table->tables[i].guid, &table_guid,
|
if (!memcmp(&sys_table->tables[i].guid, &table_guid,
|
||||||
sizeof(efi_guid_t))) {
|
sizeof(efi_guid_t))) {
|
||||||
table = sys_table->tables[i].table;
|
table = sys_table->tables[i].table;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,9 +60,8 @@ static int execute(void)
|
||||||
efi_st_printf("%u protocols installed on image handle\n",
|
efi_st_printf("%u protocols installed on image handle\n",
|
||||||
(unsigned int)protocol_buffer_count);
|
(unsigned int)protocol_buffer_count);
|
||||||
for (i = 0; i < protocol_buffer_count; ++i) {
|
for (i = 0; i < protocol_buffer_count; ++i) {
|
||||||
if (efi_st_memcmp(protocol_buffer[i],
|
if (memcmp(protocol_buffer[i], &loaded_image_protocol_guid,
|
||||||
&loaded_image_protocol_guid,
|
sizeof(efi_guid_t)))
|
||||||
sizeof(efi_guid_t)))
|
|
||||||
found = true;
|
found = true;
|
||||||
}
|
}
|
||||||
if (!found) {
|
if (!found) {
|
||||||
|
|
|
@ -322,8 +322,7 @@ static efi_status_t EFIAPI getinfo
|
||||||
efi_uintn_t *buffer_size, void *buffer)
|
efi_uintn_t *buffer_size, void *buffer)
|
||||||
{
|
{
|
||||||
if (this == &file) {
|
if (this == &file) {
|
||||||
if (efi_st_memcmp(info_type, &guid_file_info,
|
if (memcmp(info_type, &guid_file_info, sizeof(efi_guid_t)))
|
||||||
sizeof(efi_guid_t)))
|
|
||||||
return EFI_INVALID_PARAMETER;
|
return EFI_INVALID_PARAMETER;
|
||||||
if (*buffer_size >= sizeof(struct file_info)) {
|
if (*buffer_size >= sizeof(struct file_info)) {
|
||||||
boottime->copy_mem(buffer, file_info,
|
boottime->copy_mem(buffer, file_info,
|
||||||
|
@ -333,8 +332,8 @@ static efi_status_t EFIAPI getinfo
|
||||||
return EFI_BUFFER_TOO_SMALL;
|
return EFI_BUFFER_TOO_SMALL;
|
||||||
}
|
}
|
||||||
} else if (this == &volume) {
|
} else if (this == &volume) {
|
||||||
if (efi_st_memcmp(info_type, &guid_file_system_info,
|
if (memcmp(info_type, &guid_file_system_info,
|
||||||
sizeof(efi_guid_t)))
|
sizeof(efi_guid_t)))
|
||||||
return EFI_INVALID_PARAMETER;
|
return EFI_INVALID_PARAMETER;
|
||||||
if (*buffer_size >= sizeof(struct file_system_info)) {
|
if (*buffer_size >= sizeof(struct file_system_info)) {
|
||||||
boottime->copy_mem(buffer, file_system_info,
|
boottime->copy_mem(buffer, file_system_info,
|
||||||
|
|
|
@ -332,13 +332,13 @@ static int execute(void)
|
||||||
efi_st_error("Failed to get protocols per handle\n");
|
efi_st_error("Failed to get protocols per handle\n");
|
||||||
return EFI_ST_FAILURE;
|
return EFI_ST_FAILURE;
|
||||||
}
|
}
|
||||||
if (efi_st_memcmp(prot_buffer[0], &guid1, 16) &&
|
if (memcmp(prot_buffer[0], &guid1, 16) &&
|
||||||
efi_st_memcmp(prot_buffer[1], &guid1, 16)) {
|
memcmp(prot_buffer[1], &guid1, 16)) {
|
||||||
efi_st_error("Failed to get protocols per handle\n");
|
efi_st_error("Failed to get protocols per handle\n");
|
||||||
return EFI_ST_FAILURE;
|
return EFI_ST_FAILURE;
|
||||||
}
|
}
|
||||||
if (efi_st_memcmp(prot_buffer[0], &guid3, 16) &&
|
if (memcmp(prot_buffer[0], &guid3, 16) &&
|
||||||
efi_st_memcmp(prot_buffer[1], &guid3, 16)) {
|
memcmp(prot_buffer[1], &guid3, 16)) {
|
||||||
efi_st_error("Failed to get protocols per handle\n");
|
efi_st_error("Failed to get protocols per handle\n");
|
||||||
return EFI_ST_FAILURE;
|
return EFI_ST_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,8 +33,8 @@ static int setup(const efi_handle_t handle,
|
||||||
boottime = systable->boottime;
|
boottime = systable->boottime;
|
||||||
|
|
||||||
for (i = 0; i < systable->nr_tables; ++i) {
|
for (i = 0; i < systable->nr_tables; ++i) {
|
||||||
if (!efi_st_memcmp(&systable->tables[i].guid, &fdt_guid,
|
if (!memcmp(&systable->tables[i].guid, &fdt_guid,
|
||||||
sizeof(efi_guid_t))) {
|
sizeof(efi_guid_t))) {
|
||||||
if (fdt_addr) {
|
if (fdt_addr) {
|
||||||
efi_st_error("Duplicate device tree\n");
|
efi_st_error("Duplicate device tree\n");
|
||||||
return EFI_ST_FAILURE;
|
return EFI_ST_FAILURE;
|
||||||
|
|
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,
|
||||||
|
};
|
|
@ -334,9 +334,8 @@ static int execute(void)
|
||||||
* Unfortunately QEMU ignores the broadcast flag.
|
* Unfortunately QEMU ignores the broadcast flag.
|
||||||
* So we have to check for broadcasts too.
|
* So we have to check for broadcasts too.
|
||||||
*/
|
*/
|
||||||
if (efi_st_memcmp(&destaddr, &net->mode->current_address,
|
if (memcmp(&destaddr, &net->mode->current_address, ARP_HLEN) &&
|
||||||
ARP_HLEN) &&
|
memcmp(&destaddr, BROADCAST_MAC, ARP_HLEN))
|
||||||
efi_st_memcmp(&destaddr, BROADCAST_MAC, ARP_HLEN))
|
|
||||||
continue;
|
continue;
|
||||||
/*
|
/*
|
||||||
* Check this is a DHCP reply
|
* Check this is a DHCP reply
|
||||||
|
@ -360,7 +359,7 @@ static int execute(void)
|
||||||
addr = (u8 *)&buffer.p.ip_udp.ip_src;
|
addr = (u8 *)&buffer.p.ip_udp.ip_src;
|
||||||
efi_st_printf("DHCP reply received from %u.%u.%u.%u (%pm) ",
|
efi_st_printf("DHCP reply received from %u.%u.%u.%u (%pm) ",
|
||||||
addr[0], addr[1], addr[2], addr[3], &srcaddr);
|
addr[0], addr[1], addr[2], addr[3], &srcaddr);
|
||||||
if (!efi_st_memcmp(&destaddr, BROADCAST_MAC, ARP_HLEN))
|
if (!memcmp(&destaddr, BROADCAST_MAC, ARP_HLEN))
|
||||||
efi_st_printf("as broadcast message.\n");
|
efi_st_printf("as broadcast message.\n");
|
||||||
else
|
else
|
||||||
efi_st_printf("as unicast message.\n");
|
efi_st_printf("as unicast message.\n");
|
||||||
|
|
|
@ -139,7 +139,7 @@ static int execute(void)
|
||||||
return EFI_ST_FAILURE;
|
return EFI_ST_FAILURE;
|
||||||
}
|
}
|
||||||
if (!exit_data || exit_data_size != sizeof(expected_text) ||
|
if (!exit_data || exit_data_size != sizeof(expected_text) ||
|
||||||
efi_st_memcmp(exit_data, expected_text, sizeof(expected_text))) {
|
memcmp(exit_data, expected_text, sizeof(expected_text))) {
|
||||||
efi_st_error("Incorrect exit data\n");
|
efi_st_error("Incorrect exit data\n");
|
||||||
return EFI_ST_FAILURE;
|
return EFI_ST_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -102,20 +102,6 @@ u16 *efi_st_translate_code(u16 code)
|
||||||
return efi_st_unknown;
|
return efi_st_unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
int efi_st_memcmp(const void *buf1, const void *buf2, size_t length)
|
|
||||||
{
|
|
||||||
const u8 *pos1 = buf1;
|
|
||||||
const u8 *pos2 = buf2;
|
|
||||||
|
|
||||||
for (; length; --length) {
|
|
||||||
if (*pos1 != *pos2)
|
|
||||||
return *pos1 - *pos2;
|
|
||||||
++pos1;
|
|
||||||
++pos2;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int efi_st_strcmp_16_8(const u16 *buf1, const char *buf2)
|
int efi_st_strcmp_16_8(const u16 *buf1, const char *buf2)
|
||||||
{
|
{
|
||||||
for (; *buf1 || *buf2; ++buf1, ++buf2) {
|
for (; *buf1 || *buf2; ++buf1, ++buf2) {
|
||||||
|
|
|
@ -78,7 +78,7 @@ static int execute(void)
|
||||||
efi_st_error("GetVariable failed\n");
|
efi_st_error("GetVariable failed\n");
|
||||||
return EFI_ST_FAILURE;
|
return EFI_ST_FAILURE;
|
||||||
}
|
}
|
||||||
if (efi_st_memcmp(data, v + 4, 3)) {
|
if (memcmp(data, v + 4, 3)) {
|
||||||
efi_st_error("GetVariable returned wrong value\n");
|
efi_st_error("GetVariable returned wrong value\n");
|
||||||
return EFI_ST_FAILURE;
|
return EFI_ST_FAILURE;
|
||||||
}
|
}
|
||||||
|
@ -106,7 +106,7 @@ static int execute(void)
|
||||||
(unsigned int)len);
|
(unsigned int)len);
|
||||||
return EFI_ST_FAILURE;
|
return EFI_ST_FAILURE;
|
||||||
}
|
}
|
||||||
if (efi_st_memcmp(data, v, 8)) {
|
if (memcmp(data, v, 8)) {
|
||||||
efi_st_error("GetVariable returned wrong value\n");
|
efi_st_error("GetVariable returned wrong value\n");
|
||||||
return EFI_ST_FAILURE;
|
return EFI_ST_FAILURE;
|
||||||
}
|
}
|
||||||
|
@ -129,7 +129,7 @@ static int execute(void)
|
||||||
if (len != 15)
|
if (len != 15)
|
||||||
efi_st_todo("GetVariable returned wrong length %u\n",
|
efi_st_todo("GetVariable returned wrong length %u\n",
|
||||||
(unsigned int)len);
|
(unsigned int)len);
|
||||||
if (efi_st_memcmp(data, v, len))
|
if (memcmp(data, v, len))
|
||||||
efi_st_todo("GetVariable returned wrong value\n");
|
efi_st_todo("GetVariable returned wrong value\n");
|
||||||
/* Enumerate variables */
|
/* Enumerate variables */
|
||||||
boottime->set_mem(&guid, 16, 0);
|
boottime->set_mem(&guid, 16, 0);
|
||||||
|
@ -145,10 +145,10 @@ static int execute(void)
|
||||||
(unsigned int)ret);
|
(unsigned int)ret);
|
||||||
return EFI_ST_FAILURE;
|
return EFI_ST_FAILURE;
|
||||||
}
|
}
|
||||||
if (!efi_st_memcmp(&guid, &guid_vendor0, sizeof(efi_guid_t)) &&
|
if (!memcmp(&guid, &guid_vendor0, sizeof(efi_guid_t)) &&
|
||||||
!efi_st_strcmp_16_8(varname, "efi_st_var0"))
|
!efi_st_strcmp_16_8(varname, "efi_st_var0"))
|
||||||
flag |= 1;
|
flag |= 1;
|
||||||
if (!efi_st_memcmp(&guid, &guid_vendor1, sizeof(efi_guid_t)) &&
|
if (!memcmp(&guid, &guid_vendor1, sizeof(efi_guid_t)) &&
|
||||||
!efi_st_strcmp_16_8(varname, "efi_st_var1"))
|
!efi_st_strcmp_16_8(varname, "efi_st_var1"))
|
||||||
flag |= 2;
|
flag |= 2;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue