Newer
Older
const efi_guid_t *protocol, void *search_key,
efi_uintn_t *buffer_size, efi_handle_t *buffer)
EFI_ENTRY("%d, %pUl, %p, %p, %p", search_type, protocol, search_key,
buffer_size, buffer);
return EFI_EXIT(efi_locate_handle(search_type, protocol, search_key,
buffer_size, buffer));
/*
* Get the device path and handle of an device implementing a protocol.
*
* This function implements the LocateDevicePath service.
* See the Unified Extensible Firmware Interface (UEFI) specification
* for details.
*
* @protocol GUID of the protocol
* @device_path device path
* @device handle of the device
* @return status code
*/
static efi_status_t EFIAPI efi_locate_device_path(
const efi_guid_t *protocol,
struct efi_device_path **device_path,
efi_handle_t *device)
{
struct efi_object *efiobj;
EFI_ENTRY("%pUl, %p, %p", protocol, device_path, device);
efiobj = efi_dp_find_obj(*device_path, device_path);
if (!efiobj)
return EFI_EXIT(EFI_NOT_FOUND);
*device = efiobj->handle;
return EFI_EXIT(EFI_SUCCESS);
/* Collapses configuration table entries, removing index i */
static void efi_remove_configuration_table(int i)
{
struct efi_configuration_table *this = &efi_conf_table[i];
struct efi_configuration_table *next = &efi_conf_table[i+1];
struct efi_configuration_table *end = &efi_conf_table[systab.nr_tables];
memmove(this, next, (ulong)end - (ulong)next);
systab.nr_tables--;
}
/*
* Adds, updates, or removes a configuration table.
*
* This function is used for internal calls. For the API implementation of the
* InstallConfigurationTable service see efi_install_configuration_table_ext.
*
* @guid GUID of the installed table
* @table table to be installed
* @return status code
*/
efi_status_t efi_install_configuration_table(const efi_guid_t *guid, void *table)
{
int i;
/* Check for guid override */
for (i = 0; i < systab.nr_tables; i++) {
if (!guidcmp(guid, &efi_conf_table[i].guid)) {
if (table)
efi_conf_table[i].table = table;
else
efi_remove_configuration_table(i);
return EFI_SUCCESS;
if (!table)
return EFI_NOT_FOUND;
/* No override, check for overflow */
if (i >= ARRAY_SIZE(efi_conf_table))
return EFI_OUT_OF_RESOURCES;
/* Add a new entry */
memcpy(&efi_conf_table[i].guid, guid, sizeof(*guid));
efi_conf_table[i].table = table;
systab.nr_tables = i + 1;
return EFI_SUCCESS;
}
/*
* Adds, updates, or removes a configuration table.
*
* This function implements the InstallConfigurationTable service.
* See the Unified Extensible Firmware Interface (UEFI) specification
* for details.
*
* @guid GUID of the installed table
* @table table to be installed
* @return status code
*/
static efi_status_t EFIAPI efi_install_configuration_table_ext(efi_guid_t *guid,
void *table)
{
return EFI_EXIT(efi_install_configuration_table(guid, table));
/*
* Initialize a loaded_image_info + loaded_image_info object with correct
* protocols, boot-device, etc.
* @info loaded image info to be passed to the entry point of the
* image
* @obj internal object associated with the loaded image
* @device_path device path of the loaded image
* @file_path file path of the loaded image
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
*/
void efi_setup_loaded_image(struct efi_loaded_image *info, struct efi_object *obj,
struct efi_device_path *device_path,
struct efi_device_path *file_path)
{
obj->handle = info;
/*
* When asking for the device path interface, return
* bootefi_device_path
*/
obj->protocols[0].guid = &efi_guid_device_path;
obj->protocols[0].protocol_interface = device_path;
/*
* When asking for the loaded_image interface, just
* return handle which points to loaded_image_info
*/
obj->protocols[1].guid = &efi_guid_loaded_image;
obj->protocols[1].protocol_interface = info;
obj->protocols[2].guid = &efi_guid_console_control;
obj->protocols[2].protocol_interface = (void *)&efi_console_control;
obj->protocols[3].guid = &efi_guid_device_path_to_text_protocol;
obj->protocols[3].protocol_interface =
(void *)&efi_device_path_to_text;
info->file_path = file_path;
if (device_path)
info->device_handle = efi_dp_find_obj(device_path, NULL);
list_add_tail(&obj->link, &efi_obj_list);
}
/*
* Load an image using a file path.
*
* @file_path the path of the image to load
* @buffer buffer containing the loaded image
* @return status code
efi_status_t efi_load_image_from_path(struct efi_device_path *file_path,
void **buffer)
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
{
struct efi_file_info *info = NULL;
struct efi_file_handle *f;
static efi_status_t ret;
uint64_t bs;
f = efi_file_from_path(file_path);
if (!f)
return EFI_DEVICE_ERROR;
bs = 0;
EFI_CALL(ret = f->getinfo(f, (efi_guid_t *)&efi_file_info_guid,
&bs, info));
if (ret == EFI_BUFFER_TOO_SMALL) {
info = malloc(bs);
EFI_CALL(ret = f->getinfo(f, (efi_guid_t *)&efi_file_info_guid,
&bs, info));
}
if (ret != EFI_SUCCESS)
goto error;
ret = efi_allocate_pool(EFI_LOADER_DATA, info->file_size, buffer);
if (ret)
goto error;
EFI_CALL(ret = f->read(f, &info->file_size, *buffer));
error:
free(info);
EFI_CALL(f->close(f));
if (ret != EFI_SUCCESS) {
efi_free_pool(*buffer);
*buffer = NULL;
}
return ret;
}
/*
* Load an EFI image into memory.
*
* This function implements the LoadImage service.
* See the Unified Extensible Firmware Interface (UEFI) specification
* for details.
*
* @boot_policy true for request originating from the boot manager
* @parent_image the calles's image handle
* @file_path the path of the image to load
* @source_buffer memory location from which the image is installed
* @source_size size of the memory area from which the image is
* installed
* @image_handle handle for the newly installed image
* @return status code
*/
static efi_status_t EFIAPI efi_load_image(bool boot_policy,
efi_handle_t parent_image,
struct efi_device_path *file_path,
void *source_buffer,
unsigned long source_size,
efi_handle_t *image_handle)
{
struct efi_loaded_image *info;
struct efi_object *obj;
EFI_ENTRY("%d, %p, %p, %p, %ld, %p", boot_policy, parent_image,
file_path, source_buffer, source_size, image_handle);
info = calloc(1, sizeof(*info));
obj = calloc(1, sizeof(*obj));
if (!source_buffer) {
struct efi_device_path *dp, *fp;
efi_status_t ret;
ret = efi_load_image_from_path(file_path, &source_buffer);
if (ret != EFI_SUCCESS) {
free(info);
free(obj);
return EFI_EXIT(ret);
}
/*
* split file_path which contains both the device and
* file parts:
*/
efi_dp_split_file_path(file_path, &dp, &fp);
efi_setup_loaded_image(info, obj, dp, fp);
} else {
/* In this case, file_path is the "device" path, ie.
* something like a HARDWARE_DEVICE:MEMORY_MAPPED
*/
efi_setup_loaded_image(info, obj, file_path, NULL);
}
info->reserved = efi_load_pe(source_buffer, info);
if (!info->reserved) {
free(info);
free(obj);
return EFI_EXIT(EFI_UNSUPPORTED);
}
info->system_table = &systab;
info->parent_handle = parent_image;
*image_handle = info;
return EFI_EXIT(EFI_SUCCESS);
}
/*
* Call the entry point of an image.
*
* This function implements the StartImage service.
* See the Unified Extensible Firmware Interface (UEFI) specification
* for details.
*
* @image_handle handle of the image
* @exit_data_size size of the buffer
* @exit_data buffer to receive the exit data of the called image
* @return status code
static efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle,
unsigned long *exit_data_size,
s16 **exit_data)
{
ulong (*entry)(void *image_handle, struct efi_system_table *st);
struct efi_loaded_image *info = image_handle;
EFI_ENTRY("%p, %p, %p", image_handle, exit_data_size, exit_data);
entry = info->reserved;
efi_is_direct_boot = false;
/* call the image! */
if (setjmp(&info->exit_jmp)) {
/* We returned from the child image */
return EFI_EXIT(info->exit_status);
}
__efi_nesting_dec();
__efi_exit_check();
__efi_entry_check();
__efi_nesting_inc();
/* Should usually never get here */
return EFI_EXIT(EFI_SUCCESS);
}
/*
* Leave an EFI application or driver.
*
* This function implements the Exit service.
* See the Unified Extensible Firmware Interface (UEFI) specification
* for details.
*
* @image_handle handle of the application or driver that is exiting
* @exit_status status code
* @exit_data_size size of the buffer in bytes
* @exit_data buffer with data describing an error
* @return status code
static efi_status_t EFIAPI efi_exit(efi_handle_t image_handle,
efi_status_t exit_status, unsigned long exit_data_size,
int16_t *exit_data)
struct efi_loaded_image *loaded_image_info = (void*)image_handle;
EFI_ENTRY("%p, %ld, %ld, %p", image_handle, exit_status,
exit_data_size, exit_data);
/* Make sure entry/exit counts for EFI world cross-overs match */
__efi_exit_check();
/*
* But longjmp out with the U-Boot gd, not the application's, as
* the other end is a setjmp call inside EFI context.
*/
efi_restore_gd();
loaded_image_info->exit_status = exit_status;
longjmp(&loaded_image_info->exit_jmp, 1);
/*
* Unload an EFI image.
*
* This function implements the UnloadImage service.
* See the Unified Extensible Firmware Interface (UEFI) specification
* for details.
*
* @image_handle handle of the image to be unloaded
* @return status code
*/
static efi_status_t EFIAPI efi_unload_image(void *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);
}
/*
* Fix up caches for EFI payloads if necessary.
*/
static void efi_exit_caches(void)
{
#if defined(CONFIG_ARM) && !defined(CONFIG_ARM64)
/*
* Grub on 32bit ARM needs to have caches disabled before jumping into
* a zImage, but does not know of all cache layers. Give it a hand.
*/
if (efi_is_direct_boot)
cleanup_before_linux();
#endif
}
/*
* Stop boot services.
*
* This function implements the ExitBootServices service.
* See the Unified Extensible Firmware Interface (UEFI) specification
* for details.
*
* @image_handle handle of the loaded image
* @map_key key of the memory map
* @return status code
*/
static efi_status_t EFIAPI efi_exit_boot_services(void *image_handle,
unsigned long map_key)
{
EFI_ENTRY("%p, %ld", image_handle, map_key);
/* Notify that ExitBootServices is invoked. */
for (i = 0; i < ARRAY_SIZE(efi_events); ++i) {
if (efi_events[i].type != EVT_SIGNAL_EXIT_BOOT_SERVICES)
continue;
efi_signal_event(&efi_events[i]);
}
/* Make sure that notification functions are not called anymore */
efi_tpl = TPL_HIGH_LEVEL;
/* XXX Should persist EFI variables here */
board_quiesce_devices();
/* Fix up caches for EFI payloads if necessary */
efi_exit_caches();
/* This stops all lingering devices */
bootm_disable_interrupts();
/* Give the payload some time to boot */
WATCHDOG_RESET();
return EFI_EXIT(EFI_SUCCESS);
}
/*
* Get next value of the counter.
*
* This function implements the NextMonotonicCount service.
* See the Unified Extensible Firmware Interface (UEFI) specification
* for details.
*
* @count returned value of the counter
* @return status code
*/
static efi_status_t EFIAPI efi_get_next_monotonic_count(uint64_t *count)
{
static uint64_t mono = 0;
EFI_ENTRY("%p", count);
*count = mono++;
return EFI_EXIT(EFI_SUCCESS);
}
/*
* Sleep.
*
* This function implements the Stall sercive.
* See the Unified Extensible Firmware Interface (UEFI) specification
* for details.
*
* @microseconds period to sleep in microseconds
* @return status code
*/
static efi_status_t EFIAPI efi_stall(unsigned long microseconds)
{
EFI_ENTRY("%ld", microseconds);
udelay(microseconds);
return EFI_EXIT(EFI_SUCCESS);
}
/*
* Reset the watchdog timer.
*
* This function implements the SetWatchdogTimer service.
* See the Unified Extensible Firmware Interface (UEFI) specification
* for details.
*
* @timeout seconds before reset by watchdog
* @watchdog_code code to be logged when resetting
* @data_size size of buffer in bytes
* @watchdog_data buffer with data describing the reset reason
* @return status code
static efi_status_t EFIAPI efi_set_watchdog_timer(unsigned long timeout,
uint64_t watchdog_code,
unsigned long data_size,
uint16_t *watchdog_data)
{
EFI_ENTRY("%ld, 0x%"PRIx64", %ld, %p", timeout, watchdog_code,
data_size, watchdog_data);
return EFI_EXIT(efi_set_watchdog(timeout));
/*
* Connect a controller to a driver.
*
* This function implements the ConnectController service.
* See the Unified Extensible Firmware Interface (UEFI) specification
* for details.
*
* @controller_handle handle of the controller
* @driver_image_handle handle of the driver
* @remain_device_path device path of a child controller
* @recursive true to connect all child controllers
* @return status code
*/
static efi_status_t EFIAPI efi_connect_controller(
efi_handle_t controller_handle,
efi_handle_t *driver_image_handle,
struct efi_device_path *remain_device_path,
bool recursive)
{
EFI_ENTRY("%p, %p, %p, %d", controller_handle, driver_image_handle,
remain_device_path, recursive);
return EFI_EXIT(EFI_NOT_FOUND);
}
/*
* Disconnect a controller from a driver.
*
* This function implements the DisconnectController service.
* See the Unified Extensible Firmware Interface (UEFI) specification
* for details.
*
* @controller_handle handle of the controller
* @driver_image_handle handle of the driver
* @child_handle handle of the child to destroy
* @return status code
*/
static efi_status_t EFIAPI efi_disconnect_controller(void *controller_handle,
void *driver_image_handle,
void *child_handle)
{
EFI_ENTRY("%p, %p, %p", controller_handle, driver_image_handle,
child_handle);
return EFI_EXIT(EFI_INVALID_PARAMETER);
}
/*
* Close a protocol.
*
* This function implements the CloseProtocol service.
* See the Unified Extensible Firmware Interface (UEFI) specification
* for details.
*
* @handle handle on which the protocol shall be closed
* @protocol GUID of the protocol to close
* @agent_handle handle of the driver
* @controller_handle handle of the controller
* @return status code
*/
static efi_status_t EFIAPI efi_close_protocol(void *handle,
const efi_guid_t *protocol,
void *agent_handle,
void *controller_handle)
{
EFI_ENTRY("%p, %pUl, %p, %p", handle, protocol, agent_handle,
controller_handle);
return EFI_EXIT(EFI_NOT_FOUND);
}
/*
* Provide information about then open status of a protocol on a handle
*
* This function implements the OpenProtocolInformation service.
* See the Unified Extensible Firmware Interface (UEFI) specification
* for details.
*
* @handle handle for which the information shall be retrieved
* @protocol GUID of the protocol
* @entry_buffer buffer to receive the open protocol information
* @entry_count number of entries available in the buffer
* @return status code
*/
static efi_status_t EFIAPI efi_open_protocol_information(efi_handle_t handle,
const efi_guid_t *protocol,
struct efi_open_protocol_info_entry **entry_buffer,
efi_uintn_t *entry_count)
EFI_ENTRY("%p, %pUl, %p, %p", handle, protocol, entry_buffer,
entry_count);
return EFI_EXIT(EFI_NOT_FOUND);
}
/*
* Get protocols installed on a handle.
*
* This function implements the ProtocolsPerHandleService.
* See the Unified Extensible Firmware Interface (UEFI) specification
* for details.
*
* @handle handle for which the information is retrieved
* @protocol_buffer buffer with protocol GUIDs
* @protocol_buffer_count number of entries in the buffer
* @return status code
static efi_status_t EFIAPI efi_protocols_per_handle(void *handle,
efi_guid_t ***protocol_buffer,
efi_uintn_t *protocol_buffer_count)
unsigned long buffer_size;
struct efi_object *efiobj;
unsigned long i, j;
struct list_head *lhandle;
efi_status_t r;
EFI_ENTRY("%p, %p, %p", handle, protocol_buffer,
protocol_buffer_count);
if (!handle || !protocol_buffer || !protocol_buffer_count)
return EFI_EXIT(EFI_INVALID_PARAMETER);
*protocol_buffer = NULL;
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
list_for_each(lhandle, &efi_obj_list) {
efiobj = list_entry(lhandle, struct efi_object, link);
if (efiobj->handle != handle)
continue;
/* Count protocols */
for (i = 0; i < ARRAY_SIZE(efiobj->protocols); i++) {
if (efiobj->protocols[i].guid)
++*protocol_buffer_count;
}
/* Copy guids */
if (*protocol_buffer_count) {
buffer_size = sizeof(efi_guid_t *) *
*protocol_buffer_count;
r = efi_allocate_pool(EFI_ALLOCATE_ANY_PAGES,
buffer_size,
(void **)protocol_buffer);
if (r != EFI_SUCCESS)
return EFI_EXIT(r);
j = 0;
for (i = 0; i < ARRAY_SIZE(efiobj->protocols); ++i) {
if (efiobj->protocols[i].guid) {
(*protocol_buffer)[j] = (void *)
efiobj->protocols[i].guid;
++j;
}
}
}
break;
}
return EFI_EXIT(EFI_SUCCESS);
/*
* Locate handles implementing a protocol.
*
* This function implements the LocateHandleBuffer service.
* See the Unified Extensible Firmware Interface (UEFI) specification
* for details.
*
* @search_type selection criterion
* @protocol GUID of the protocol
* @search_key registration key
* @no_handles number of returned handles
* @buffer buffer with the returned handles
* @return status code
*/
static efi_status_t EFIAPI efi_locate_handle_buffer(
enum efi_locate_search_type search_type,
const efi_guid_t *protocol, void *search_key,
efi_uintn_t *no_handles, efi_handle_t **buffer)
efi_uintn_t buffer_size = 0;
EFI_ENTRY("%d, %pUl, %p, %p, %p", search_type, protocol, search_key,
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
if (!no_handles || !buffer) {
r = EFI_INVALID_PARAMETER;
goto out;
}
*no_handles = 0;
*buffer = NULL;
r = efi_locate_handle(search_type, protocol, search_key, &buffer_size,
*buffer);
if (r != EFI_BUFFER_TOO_SMALL)
goto out;
r = efi_allocate_pool(EFI_ALLOCATE_ANY_PAGES, buffer_size,
(void **)buffer);
if (r != EFI_SUCCESS)
goto out;
r = efi_locate_handle(search_type, protocol, search_key, &buffer_size,
*buffer);
if (r == EFI_SUCCESS)
*no_handles = buffer_size / sizeof(void *);
out:
return EFI_EXIT(r);
/*
* Find an interface implementing a protocol.
*
* This function implements the LocateProtocol service.
* See the Unified Extensible Firmware Interface (UEFI) specification
* for details.
*
* @protocol GUID of the protocol
* @registration registration key passed to the notification function
* @protocol_interface interface implementing the protocol
* @return status code
static efi_status_t EFIAPI efi_locate_protocol(const efi_guid_t *protocol,
void *registration,
void **protocol_interface)
{
struct list_head *lhandle;
EFI_ENTRY("%pUl, %p, %p", protocol, registration, protocol_interface);
if (!protocol || !protocol_interface)
return EFI_EXIT(EFI_INVALID_PARAMETER);
EFI_PRINT_GUID("protocol", protocol);
list_for_each(lhandle, &efi_obj_list) {
struct efi_object *efiobj;
efiobj = list_entry(lhandle, struct efi_object, link);
for (i = 0; i < ARRAY_SIZE(efiobj->protocols); i++) {
struct efi_handler *handler = &efiobj->protocols[i];
if (!handler->guid)
continue;
if (!guidcmp(handler->guid, protocol)) {
*protocol_interface =
handler->protocol_interface;
return EFI_EXIT(EFI_SUCCESS);
}
*protocol_interface = NULL;
return EFI_EXIT(EFI_NOT_FOUND);
}
/*
* Install multiple protocol interfaces.
*
* This function implements the MultipleProtocolInterfaces service.
* See the Unified Extensible Firmware Interface (UEFI) specification
* for details.
*
* @handle handle on which the protocol interfaces shall be installed
* @... NULL terminated argument list with pairs of protocol GUIDS and
* interfaces
* @return status code
*/
static efi_status_t EFIAPI efi_install_multiple_protocol_interfaces(
void **handle, ...)
{
EFI_ENTRY("%p", handle);
va_list argptr;
const efi_guid_t *protocol;
void *protocol_interface;
efi_status_t r = EFI_SUCCESS;
int i = 0;
if (!handle)
return EFI_EXIT(EFI_INVALID_PARAMETER);
va_start(argptr, handle);
for (;;) {
protocol = va_arg(argptr, efi_guid_t*);
if (!protocol)
break;
protocol_interface = va_arg(argptr, void*);
r = EFI_CALL(efi_install_protocol_interface(
handle, protocol,
EFI_NATIVE_INTERFACE,
protocol_interface));
if (r != EFI_SUCCESS)
break;
i++;
}
va_end(argptr);
if (r == EFI_SUCCESS)
return EFI_EXIT(r);
/* If an error occurred undo all changes. */
va_start(argptr, handle);
for (; i; --i) {
protocol = va_arg(argptr, efi_guid_t*);
protocol_interface = va_arg(argptr, void*);
EFI_CALL(efi_uninstall_protocol_interface(handle, protocol,
protocol_interface));
}
va_end(argptr);
return EFI_EXIT(r);
/*
* Uninstall multiple protocol interfaces.
*
* This function implements the UninstallMultipleProtocolInterfaces service.
* See the Unified Extensible Firmware Interface (UEFI) specification
* for details.
*
* @handle handle from which the protocol interfaces shall be removed
* @... NULL terminated argument list with pairs of protocol GUIDS and
* interfaces
* @return status code
*/
static efi_status_t EFIAPI efi_uninstall_multiple_protocol_interfaces(
void *handle, ...)
{
EFI_ENTRY("%p", handle);
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
va_list argptr;
const efi_guid_t *protocol;
void *protocol_interface;
efi_status_t r = EFI_SUCCESS;
size_t i = 0;
if (!handle)
return EFI_EXIT(EFI_INVALID_PARAMETER);
va_start(argptr, handle);
for (;;) {
protocol = va_arg(argptr, efi_guid_t*);
if (!protocol)
break;
protocol_interface = va_arg(argptr, void*);
r = EFI_CALL(efi_uninstall_protocol_interface(
handle, protocol,
protocol_interface));
if (r != EFI_SUCCESS)
break;
i++;
}
va_end(argptr);
if (r == EFI_SUCCESS)
return EFI_EXIT(r);
/* If an error occurred undo all changes. */
va_start(argptr, handle);
for (; i; --i) {
protocol = va_arg(argptr, efi_guid_t*);
protocol_interface = va_arg(argptr, void*);
EFI_CALL(efi_install_protocol_interface(&handle, protocol,
EFI_NATIVE_INTERFACE,
protocol_interface));
}
va_end(argptr);
return EFI_EXIT(r);
/*
* Calculate cyclic redundancy code.
*
* This function implements the CalculateCrc32 service.
* See the Unified Extensible Firmware Interface (UEFI) specification
* for details.
*
* @data buffer with data
* @data_size size of buffer in bytes
* @crc32_p cyclic redundancy code
* @return status code
*/
static efi_status_t EFIAPI efi_calculate_crc32(void *data,
unsigned long data_size,
uint32_t *crc32_p)
{
EFI_ENTRY("%p, %ld", data, data_size);
*crc32_p = crc32(0, data, data_size);
return EFI_EXIT(EFI_SUCCESS);
}
/*
* Copy memory.
*
* This function implements the CopyMem service.
* See the Unified Extensible Firmware Interface (UEFI) specification
* for details.
*
* @destination destination of the copy operation
* @source source of the copy operation
* @length number of bytes to copy
*/
static void EFIAPI efi_copy_mem(void *destination, const void *source,
size_t length)
EFI_ENTRY("%p, %p, %ld", destination, source, (unsigned long)length);
memcpy(destination, source, length);
EFI_EXIT(EFI_SUCCESS);
/*
* Fill memory with a byte value.
*
* This function implements the SetMem service.
* See the Unified Extensible Firmware Interface (UEFI) specification
* for details.
*
* @buffer buffer to fill
* @size size of buffer in bytes
* @value byte to copy to the buffer
*/
static void EFIAPI efi_set_mem(void *buffer, size_t size, uint8_t value)
EFI_ENTRY("%p, %ld, 0x%x", buffer, (unsigned long)size, value);
EFI_EXIT(EFI_SUCCESS);
/*
* Open protocol interface on a handle.
*
* This function implements the OpenProtocol interface.
* See the Unified Extensible Firmware Interface (UEFI) specification
* for details.
*
* @handle handle on which the protocol shall be opened
* @protocol GUID of the protocol
* @protocol_interface interface implementing the protocol
* @agent_handle handle of the driver
* @controller_handle handle of the controller
* @attributes attributes indicating how to open the protocol
* @return status code
*/
static efi_status_t EFIAPI efi_open_protocol(
void *handle, const efi_guid_t *protocol,
void **protocol_interface, void *agent_handle,
void *controller_handle, uint32_t attributes)
{
struct list_head *lhandle;
int i;
efi_status_t r = EFI_INVALID_PARAMETER;
EFI_ENTRY("%p, %pUl, %p, %p, %p, 0x%x", handle, protocol,
protocol_interface, agent_handle, controller_handle,
attributes);
if (!handle || !protocol ||
(!protocol_interface && attributes !=
EFI_OPEN_PROTOCOL_TEST_PROTOCOL)) {
goto out;
}
EFI_PRINT_GUID("protocol", protocol);
switch (attributes) {
case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL:
case EFI_OPEN_PROTOCOL_GET_PROTOCOL:
case EFI_OPEN_PROTOCOL_TEST_PROTOCOL:
break;
case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER:
if (controller_handle == handle)
goto out;
case EFI_OPEN_PROTOCOL_BY_DRIVER:
case EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE:
if (controller_handle == NULL)
goto out;
case EFI_OPEN_PROTOCOL_EXCLUSIVE:
if (agent_handle == NULL)
goto out;
break;
default:
list_for_each(lhandle, &efi_obj_list) {
struct efi_object *efiobj;
efiobj = list_entry(lhandle, struct efi_object, link);
if (efiobj->handle != handle)
continue;
for (i = 0; i < ARRAY_SIZE(efiobj->protocols); i++) {
struct efi_handler *handler = &efiobj->protocols[i];
const efi_guid_t *hprotocol = handler->guid;
if (!hprotocol)
if (!guidcmp(hprotocol, protocol)) {
if (attributes !=
EFI_OPEN_PROTOCOL_TEST_PROTOCOL) {
*protocol_interface =
handler->protocol_interface;
}
r = EFI_SUCCESS;
unsupported:
r = EFI_UNSUPPORTED;
out:
return EFI_EXIT(r);
}
/*
* Get interface of a protocol on a handle.
*