diff options
Diffstat (limited to 'lib/efi/efi.c')
-rw-r--r-- | lib/efi/efi.c | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/lib/efi/efi.c b/lib/efi/efi.c new file mode 100644 index 00000000000..81af27caab1 --- /dev/null +++ b/lib/efi/efi.c @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2015 Google, Inc + * + * SPDX-License-Identifier: GPL-2.0+ + * + * EFI information obtained here: + * http://wiki.phoenix.com/wiki/index.php/EFI_BOOT_SERVICES + * + * Common EFI functions + */ + +#include <common.h> +#include <debug_uart.h> +#include <errno.h> +#include <linux/err.h> +#include <linux/types.h> +#include <efi.h> +#include <efi_api.h> + +DECLARE_GLOBAL_DATA_PTR; + +/* + * Unfortunately we cannot access any code outside what is built especially + * for the stub. lib/string.c is already being built for the U-Boot payload + * so it uses the wrong compiler flags. Add our own memset() here. + */ +static void efi_memset(void *ptr, int ch, int size) +{ + char *dest = ptr; + + while (size-- > 0) + *dest++ = ch; +} + +/* + * Since the EFI stub cannot access most of the U-Boot code, add our own + * simple console output functions here. The EFI app will not use these since + * it can use the normal console. + */ +void efi_putc(struct efi_priv *priv, const char ch) +{ + struct efi_simple_text_output_protocol *con = priv->sys_table->con_out; + uint16_t ucode[2]; + + ucode[0] = ch; + ucode[1] = '\0'; + con->output_string(con, ucode); +} + +void efi_puts(struct efi_priv *priv, const char *str) +{ + while (*str) + efi_putc(priv, *str++); +} + +int efi_init(struct efi_priv *priv, const char *banner, efi_handle_t image, + struct efi_system_table *sys_table) +{ + efi_guid_t loaded_image_guid = LOADED_IMAGE_PROTOCOL_GUID; + struct efi_boot_services *boot = sys_table->boottime; + struct efi_loaded_image *loaded_image; + int ret; + + efi_memset(priv, '\0', sizeof(*priv)); + priv->sys_table = sys_table; + priv->boot = sys_table->boottime; + priv->parent_image = image; + priv->run = sys_table->runtime; + + efi_puts(priv, "U-Boot EFI "); + efi_puts(priv, banner); + efi_putc(priv, ' '); + + ret = boot->open_protocol(priv->parent_image, &loaded_image_guid, + (void **)&loaded_image, &priv->parent_image, + NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (ret) { + efi_puts(priv, "Failed to get loaded image protocol\n"); + return ret; + } + priv->image_data_type = loaded_image->image_data_type; + + return 0; +} + +void *efi_malloc(struct efi_priv *priv, int size, efi_status_t *retp) +{ + struct efi_boot_services *boot = priv->boot; + void *buf = NULL; + + *retp = boot->allocate_pool(priv->image_data_type, size, &buf); + + return buf; +} + +void efi_free(struct efi_priv *priv, void *ptr) +{ + struct efi_boot_services *boot = priv->boot; + + boot->free_pool(ptr); +} |