aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/efi_loader/Makefile3
-rw-r--r--lib/efi_loader/efi_console.c6
-rw-r--r--lib/efi_loader/efi_dt_fixup.c160
-rw-r--r--lib/efi_loader/efi_file.c317
-rw-r--r--lib/efi_loader/efi_image_loader.c80
-rw-r--r--lib/efi_loader/efi_memory.c2
-rw-r--r--lib/efi_loader/efi_root_node.c6
-rw-r--r--lib/efi_loader/helloworld.c167
-rw-r--r--lib/efi_selftest/dtbdump.c310
9 files changed, 894 insertions, 157 deletions
diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile
index 462d4d9ac4..412fa88245 100644
--- a/lib/efi_loader/Makefile
+++ b/lib/efi_loader/Makefile
@@ -29,6 +29,9 @@ obj-y += efi_console.o
obj-y += efi_device_path.o
obj-$(CONFIG_EFI_DEVICE_PATH_TO_TEXT) += efi_device_path_to_text.o
obj-y += efi_device_path_utilities.o
+ifeq ($(CONFIG_GENERATE_ACPI_TABLE),)
+obj-y += efi_dt_fixup.o
+endif
obj-y += efi_file.o
obj-$(CONFIG_EFI_LOADER_HII) += efi_hii.o
obj-y += efi_image_loader.o
diff --git a/lib/efi_loader/efi_console.c b/lib/efi_loader/efi_console.c
index 705109596e..edcfce7bec 100644
--- a/lib/efi_loader/efi_console.c
+++ b/lib/efi_loader/efi_console.c
@@ -141,12 +141,12 @@ static int term_read_reply(int *n, int num, char end_char)
*/
static efi_status_t EFIAPI efi_cout_output_string(
struct efi_simple_text_output_protocol *this,
- const efi_string_t string)
+ const u16 *string)
{
struct simple_text_output_mode *con = &efi_con_mode;
struct cout_mode *mode = &efi_cout_modes[con->mode];
char *buf, *pos;
- u16 *p;
+ const u16 *p;
efi_status_t ret = EFI_SUCCESS;
EFI_ENTRY("%p, %p", this, string);
@@ -230,7 +230,7 @@ out:
*/
static efi_status_t EFIAPI efi_cout_test_string(
struct efi_simple_text_output_protocol *this,
- const efi_string_t string)
+ const u16 *string)
{
EFI_ENTRY("%p, %p", this, string);
return EFI_EXIT(EFI_SUCCESS);
diff --git a/lib/efi_loader/efi_dt_fixup.c b/lib/efi_loader/efi_dt_fixup.c
new file mode 100644
index 0000000000..5f0ae5c338
--- /dev/null
+++ b/lib/efi_loader/efi_dt_fixup.c
@@ -0,0 +1,160 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * EFI_DT_FIXUP_PROTOCOL
+ *
+ * Copyright (c) 2020 Heinrich Schuchardt
+ */
+
+#include <common.h>
+#include <efi_dt_fixup.h>
+#include <efi_loader.h>
+#include <mapmem.h>
+
+static efi_status_t EFIAPI efi_dt_fixup(struct efi_dt_fixup_protocol *this,
+ void *dtb,
+ efi_uintn_t *buffer_size,
+ u32 flags);
+
+struct efi_dt_fixup_protocol efi_dt_fixup_prot = {
+ .revision = EFI_DT_FIXUP_PROTOCOL_REVISION,
+ .fixup = efi_dt_fixup
+};
+
+const efi_guid_t efi_guid_dt_fixup_protocol = EFI_DT_FIXUP_PROTOCOL_GUID;
+
+/**
+ * efi_reserve_memory() - add reserved memory to memory map
+ *
+ * @addr: start address of the reserved memory range
+ * @size: size of the reserved memory range
+ * @nomap: indicates that the memory range shall not be accessed by the
+ * UEFI payload
+ */
+static void efi_reserve_memory(u64 addr, u64 size, bool nomap)
+{
+ int type;
+ efi_uintn_t ret;
+
+ /* Convert from sandbox address space. */
+ addr = (uintptr_t)map_sysmem(addr, 0);
+
+ if (nomap)
+ type = EFI_RESERVED_MEMORY_TYPE;
+ else
+ type = EFI_BOOT_SERVICES_DATA;
+
+ ret = efi_add_memory_map(addr, size, type);
+ if (ret != EFI_SUCCESS)
+ log_err("Reserved memory mapping failed addr %llx size %llx\n",
+ addr, size);
+}
+
+/**
+ * efi_carve_out_dt_rsv() - Carve out DT reserved memory ranges
+ *
+ * The mem_rsv entries of the FDT are added to the memory map. Any failures are
+ * ignored because this is not critical and we would rather continue to try to
+ * boot.
+ *
+ * @fdt: Pointer to device tree
+ */
+void efi_carve_out_dt_rsv(void *fdt)
+{
+ int nr_rsv, i;
+ u64 addr, size;
+ int nodeoffset, subnode;
+
+ nr_rsv = fdt_num_mem_rsv(fdt);
+
+ /* Look for an existing entry and add it to the efi mem map. */
+ for (i = 0; i < nr_rsv; i++) {
+ if (fdt_get_mem_rsv(fdt, i, &addr, &size) != 0)
+ continue;
+ efi_reserve_memory(addr, size, false);
+ }
+
+ /* process reserved-memory */
+ nodeoffset = fdt_subnode_offset(fdt, 0, "reserved-memory");
+ if (nodeoffset >= 0) {
+ subnode = fdt_first_subnode(fdt, nodeoffset);
+ while (subnode >= 0) {
+ fdt_addr_t fdt_addr;
+ fdt_size_t fdt_size;
+
+ /* check if this subnode has a reg property */
+ fdt_addr = fdtdec_get_addr_size_auto_parent(
+ fdt, nodeoffset, subnode,
+ "reg", 0, &fdt_size, false);
+ /*
+ * The /reserved-memory node may have children with
+ * a size instead of a reg property.
+ */
+ if (fdt_addr != FDT_ADDR_T_NONE &&
+ fdtdec_get_is_enabled(fdt, subnode)) {
+ bool nomap;
+
+ nomap = !!fdt_getprop(fdt, subnode, "no-map",
+ NULL);
+ efi_reserve_memory(fdt_addr, fdt_size, nomap);
+ }
+ subnode = fdt_next_subnode(fdt, subnode);
+ }
+ }
+}
+
+static efi_status_t EFIAPI efi_dt_fixup(struct efi_dt_fixup_protocol *this,
+ void *dtb,
+ efi_uintn_t *buffer_size,
+ u32 flags)
+{
+ efi_status_t ret;
+ size_t required_size;
+ bootm_headers_t img = { 0 };
+
+ EFI_ENTRY("%p, %p, %p, %d", this, dtb, buffer_size, flags);
+
+ if (this != &efi_dt_fixup_prot || !dtb || !buffer_size ||
+ !flags || (flags & ~EFI_DT_ALL)) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+ if (fdt_check_header(dtb)) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+ if (flags & EFI_DT_APPLY_FIXUPS) {
+ required_size = fdt_off_dt_strings(dtb) +
+ fdt_size_dt_strings(dtb) +
+ 0x3000;
+ } else {
+ required_size = fdt_totalsize(dtb);
+ }
+ if (required_size > *buffer_size) {
+ *buffer_size = required_size;
+ ret = EFI_BUFFER_TOO_SMALL;
+ goto out;
+ }
+ fdt_set_totalsize(dtb, *buffer_size);
+
+ if (flags & EFI_DT_APPLY_FIXUPS) {
+ if (image_setup_libfdt(&img, dtb, 0, NULL)) {
+ log_err("failed to process device tree\n");
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+ }
+ if (flags & EFI_DT_RESERVE_MEMORY)
+ efi_carve_out_dt_rsv(dtb);
+
+ if (EFI_DT_INSTALL_TABLE) {
+ ret = efi_install_configuration_table(&efi_guid_fdt, dtb);
+ if (ret != EFI_SUCCESS) {
+ log_err("ERROR: failed to install device tree\n");
+ goto out;
+ }
+ }
+
+ ret = EFI_SUCCESS;
+out:
+ return EFI_EXIT(ret);
+}
diff --git a/lib/efi_loader/efi_file.c b/lib/efi_loader/efi_file.c
index 72b7ec1e63..8ece8e71ee 100644
--- a/lib/efi_loader/efi_file.c
+++ b/lib/efi_loader/efi_file.c
@@ -246,18 +246,16 @@ error:
return NULL;
}
-static efi_status_t EFIAPI efi_file_open(struct efi_file_handle *file,
- struct efi_file_handle **new_handle,
- u16 *file_name, u64 open_mode, u64 attributes)
+static efi_status_t efi_file_open_int(struct efi_file_handle *this,
+ struct efi_file_handle **new_handle,
+ u16 *file_name, u64 open_mode,
+ u64 attributes)
{
- struct file_handle *fh = to_fh(file);
+ struct file_handle *fh = to_fh(this);
efi_status_t ret;
- EFI_ENTRY("%p, %p, \"%ls\", %llx, %llu", file, new_handle,
- file_name, open_mode, attributes);
-
/* Check parameters */
- if (!file || !new_handle || !file_name) {
+ if (!this || !new_handle || !file_name) {
ret = EFI_INVALID_PARAMETER;
goto out;
}
@@ -292,6 +290,75 @@ static efi_status_t EFIAPI efi_file_open(struct efi_file_handle *file,
ret = EFI_NOT_FOUND;
}
out:
+ return ret;
+}
+
+/**
+ * efi_file_open_()
+ *
+ * This function implements the Open service of the File Protocol.
+ * See the UEFI spec for details.
+ *
+ * @this: EFI_FILE_PROTOCOL instance
+ * @new_handle: on return pointer to file handle
+ * @file_name: file name
+ * @open_mode: mode to open the file (read, read/write, create/read/write)
+ * @attributes: attributes for newly created file
+ */
+static efi_status_t EFIAPI efi_file_open(struct efi_file_handle *this,
+ struct efi_file_handle **new_handle,
+ u16 *file_name, u64 open_mode,
+ u64 attributes)
+{
+ efi_status_t ret;
+
+ EFI_ENTRY("%p, %p, \"%ls\", %llx, %llu", this, new_handle,
+ file_name, open_mode, attributes);
+
+ ret = efi_file_open_int(this, new_handle, file_name, open_mode,
+ attributes);
+
+ return EFI_EXIT(ret);
+}
+
+/**
+ * efi_file_open_ex() - open file asynchronously
+ *
+ * This function implements the OpenEx service of the File Protocol.
+ * See the UEFI spec for details.
+ *
+ * @this: EFI_FILE_PROTOCOL instance
+ * @new_handle: on return pointer to file handle
+ * @file_name: file name
+ * @open_mode: mode to open the file (read, read/write, create/read/write)
+ * @attributes: attributes for newly created file
+ * @token: transaction token
+ */
+static efi_status_t EFIAPI efi_file_open_ex(struct efi_file_handle *this,
+ struct efi_file_handle **new_handle,
+ u16 *file_name, u64 open_mode,
+ u64 attributes,
+ struct efi_file_io_token *token)
+{
+ efi_status_t ret;
+
+ EFI_ENTRY("%p, %p, \"%ls\", %llx, %llu, %p", this, new_handle,
+ file_name, open_mode, attributes, token);
+
+ if (!token) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+
+ ret = efi_file_open_int(this, new_handle, file_name, open_mode,
+ attributes);
+
+ if (ret == EFI_SUCCESS && token->event) {
+ token->status = EFI_SUCCESS;
+ efi_signal_event(token->event);
+ }
+
+out:
return EFI_EXIT(ret);
}
@@ -441,19 +508,15 @@ static efi_status_t dir_read(struct file_handle *fh, u64 *buffer_size,
return EFI_SUCCESS;
}
-static efi_status_t EFIAPI efi_file_read(struct efi_file_handle *file,
- efi_uintn_t *buffer_size, void *buffer)
+static efi_status_t efi_file_read_int(struct efi_file_handle *this,
+ efi_uintn_t *buffer_size, void *buffer)
{
- struct file_handle *fh = to_fh(file);
+ struct file_handle *fh = to_fh(this);
efi_status_t ret = EFI_SUCCESS;
u64 bs;
- EFI_ENTRY("%p, %p, %p", file, buffer_size, buffer);
-
- if (!buffer_size) {
- ret = EFI_INVALID_PARAMETER;
- goto error;
- }
+ if (!this || !buffer_size || !buffer)
+ return EFI_INVALID_PARAMETER;
bs = *buffer_size;
if (fh->isdir)
@@ -465,34 +528,77 @@ static efi_status_t EFIAPI efi_file_read(struct efi_file_handle *file,
else
*buffer_size = SIZE_MAX;
-error:
+ return ret;
+}
+
+/**
+ * efi_file_read() - read file
+ *
+ * This function implements the Read() service of the EFI_FILE_PROTOCOL.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * @this: file protocol instance
+ * @buffer_size: number of bytes to read
+ * @buffer: read buffer
+ * Return: status code
+ */
+static efi_status_t EFIAPI efi_file_read(struct efi_file_handle *this,
+ efi_uintn_t *buffer_size, void *buffer)
+{
+ efi_status_t ret;
+
+ EFI_ENTRY("%p, %p, %p", this, buffer_size, buffer);
+
+ ret = efi_file_read_int(this, buffer_size, buffer);
+
return EFI_EXIT(ret);
}
/**
- * efi_file_write() - write to file
+ * efi_file_read_ex() - read file asynchonously
*
- * This function implements the Write() service of the EFI_FILE_PROTOCOL.
+ * This function implements the ReadEx() service of the EFI_FILE_PROTOCOL.
*
* See the Unified Extensible Firmware Interface (UEFI) specification for
* details.
*
- * @file: file handle
- * @buffer_size: number of bytes to write
- * @buffer: buffer with the bytes to write
+ * @this: file protocol instance
+ * @token: transaction token
* Return: status code
*/
-static efi_status_t EFIAPI efi_file_write(struct efi_file_handle *file,
- efi_uintn_t *buffer_size,
- void *buffer)
+static efi_status_t EFIAPI efi_file_read_ex(struct efi_file_handle *this,
+ struct efi_file_io_token *token)
{
- struct file_handle *fh = to_fh(file);
+ efi_status_t ret;
+
+ EFI_ENTRY("%p, %p", this, token);
+
+ if (!token) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+
+ ret = efi_file_read_int(this, &token->buffer_size, token->buffer);
+
+ if (ret == EFI_SUCCESS && token->event) {
+ token->status = EFI_SUCCESS;
+ efi_signal_event(token->event);
+ }
+
+out:
+ return EFI_EXIT(ret);
+}
+
+static efi_status_t efi_file_write_int(struct efi_file_handle *this,
+ efi_uintn_t *buffer_size, void *buffer)
+{
+ struct file_handle *fh = to_fh(this);
efi_status_t ret = EFI_SUCCESS;
loff_t actwrite;
- EFI_ENTRY("%p, %p, %p", file, buffer_size, buffer);
-
- if (!file || !buffer_size || !buffer) {
+ if (!this || !buffer_size || !buffer) {
ret = EFI_INVALID_PARAMETER;
goto out;
}
@@ -521,6 +627,67 @@ static efi_status_t EFIAPI efi_file_write(struct efi_file_handle *file,
fh->offset += actwrite;
out:
+ return ret;
+}
+
+/**
+ * efi_file_write() - write to file
+ *
+ * This function implements the Write() service of the EFI_FILE_PROTOCOL.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * @this: file protocol instance
+ * @buffer_size: number of bytes to write
+ * @buffer: buffer with the bytes to write
+ * Return: status code
+ */
+static efi_status_t EFIAPI efi_file_write(struct efi_file_handle *this,
+ efi_uintn_t *buffer_size,
+ void *buffer)
+{
+ efi_status_t ret;
+
+ EFI_ENTRY("%p, %p, %p", this, buffer_size, buffer);
+
+ ret = efi_file_write_int(this, buffer_size, buffer);
+
+ return EFI_EXIT(ret);
+}
+
+/**
+ * efi_file_write_ex() - write to file
+ *
+ * This function implements the WriteEx() service of the EFI_FILE_PROTOCOL.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * @this: file protocol instance
+ * @token: transaction token
+ * Return: status code
+ */
+static efi_status_t EFIAPI efi_file_write_ex(struct efi_file_handle *this,
+ struct efi_file_io_token *token)
+{
+ efi_status_t ret;
+
+ EFI_ENTRY("%p, %p", this, token);
+
+ if (!token) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+
+ ret = efi_file_write_int(this, &token->buffer_size, token->buffer);
+
+ if (ret == EFI_SUCCESS && token->event) {
+ token->status = EFI_SUCCESS;
+ efi_signal_event(token->event);
+ }
+
+out:
return EFI_EXIT(ret);
}
@@ -761,36 +928,84 @@ out:
return EFI_EXIT(ret);
}
-static efi_status_t EFIAPI efi_file_flush(struct efi_file_handle *file)
+/**
+ * efi_file_flush_int() - flush file
+ *
+ * This is the internal implementation of the Flush() and FlushEx() services of
+ * the EFI_FILE_PROTOCOL.
+ *
+ * @this: file protocol instance
+ * Return: status code
+ */
+static efi_status_t efi_file_flush_int(struct efi_file_handle *this)
{
- EFI_ENTRY("%p", file);
- return EFI_EXIT(EFI_SUCCESS);
-}
+ struct file_handle *fh = to_fh(this);
-static efi_status_t EFIAPI efi_file_open_ex(struct efi_file_handle *file,
- struct efi_file_handle **new_handle,
- u16 *file_name, u64 open_mode, u64 attributes,
- struct efi_file_io_token *token)
-{
- return EFI_UNSUPPORTED;
-}
+ if (!this)
+ return EFI_INVALID_PARAMETER;
-static efi_status_t EFIAPI efi_file_read_ex(struct efi_file_handle *file,
- struct efi_file_io_token *token)
-{
- return EFI_UNSUPPORTED;
+ if (!(fh->open_mode & EFI_FILE_MODE_WRITE))
+ return EFI_ACCESS_DENIED;
+
+ /* TODO: flush for file position after end of file */
+ return EFI_SUCCESS;
}
-static efi_status_t EFIAPI efi_file_write_ex(struct efi_file_handle *file,
- struct efi_file_io_token *token)
+/**
+ * efi_file_flush() - flush file
+ *
+ * This function implements the Flush() service of the EFI_FILE_PROTOCOL.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * @this: file protocol instance
+ * Return: status code
+ */
+static efi_status_t EFIAPI efi_file_flush(struct efi_file_handle *this)
{
- return EFI_UNSUPPORTED;
+ efi_status_t ret;
+
+ EFI_ENTRY("%p", this);
+
+ ret = efi_file_flush_int(this);
+
+ return EFI_EXIT(ret);
}
-static efi_status_t EFIAPI efi_file_flush_ex(struct efi_file_handle *file,
- struct efi_file_io_token *token)
+/**
+ * efi_file_flush_ex() - flush file
+ *
+ * This function implements the FlushEx() service of the EFI_FILE_PROTOCOL.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * @this: file protocol instance
+ * @token: transaction token
+ * Return: status code
+ */
+static efi_status_t EFIAPI efi_file_flush_ex(struct efi_file_handle *this,
+ struct efi_file_io_token *token)
{
- return EFI_UNSUPPORTED;
+ efi_status_t ret;
+
+ EFI_ENTRY("%p, %p", this, token);
+
+ if (!token) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+
+ ret = efi_file_flush_int(this);
+
+ if (ret == EFI_SUCCESS && token->event) {
+ token->status = EFI_SUCCESS;
+ efi_signal_event(token->event);
+ }
+
+out:
+ return EFI_EXIT(ret);
}
static const struct efi_file_handle efi_file_handle_protocol = {
diff --git a/lib/efi_loader/efi_image_loader.c b/lib/efi_loader/efi_image_loader.c
index 94f76ef6b8..d4dd9e9433 100644
--- a/lib/efi_loader/efi_image_loader.c
+++ b/lib/efi_loader/efi_image_loader.c
@@ -675,6 +675,46 @@ static bool efi_image_authenticate(void *efi, size_t efi_size)
}
#endif /* CONFIG_EFI_SECURE_BOOT */
+
+/**
+ * efi_check_pe() - check if a memory buffer contains a PE-COFF image
+ *
+ * @buffer: buffer to check
+ * @size: size of buffer
+ * @nt_header: on return pointer to NT header of PE-COFF image
+ * Return: EFI_SUCCESS if the buffer contains a PE-COFF image
+ */
+efi_status_t efi_check_pe(void *buffer, size_t size, void **nt_header)
+{
+ IMAGE_DOS_HEADER *dos = buffer;
+ IMAGE_NT_HEADERS32 *nt;
+
+ if (size < sizeof(*dos))
+ return EFI_INVALID_PARAMETER;
+
+ /* Check for DOS magix */
+ if (dos->e_magic != IMAGE_DOS_SIGNATURE)
+ return EFI_INVALID_PARAMETER;
+
+ /*
+ * Check if the image section header fits into the file. Knowing that at
+ * least one section header follows we only need to check for the length
+ * of the 64bit header which is longer than the 32bit header.
+ */
+ if (size < dos->e_lfanew + sizeof(IMAGE_NT_HEADERS32))
+ return EFI_INVALID_PARAMETER;
+ nt = (IMAGE_NT_HEADERS32 *)((u8 *)buffer + dos->e_lfanew);
+
+ /* Check for PE-COFF magic */
+ if (nt->Signature != IMAGE_NT_SIGNATURE)
+ return EFI_INVALID_PARAMETER;
+
+ if (nt_header)
+ *nt_header = nt;
+
+ return EFI_SUCCESS;
+}
+
/**
* efi_load_pe() - relocate EFI binary
*
@@ -705,36 +745,10 @@ efi_status_t efi_load_pe(struct efi_loaded_image_obj *handle,
int supported = 0;
efi_status_t ret;
- /* Sanity check for a file header */
- if (efi_size < sizeof(*dos)) {
- log_err("Truncated DOS Header\n");
- ret = EFI_LOAD_ERROR;
- goto err;
- }
-
- dos = efi;
- if (dos->e_magic != IMAGE_DOS_SIGNATURE) {
- log_err("Invalid DOS Signature\n");
- ret = EFI_LOAD_ERROR;
- goto err;
- }
-
- /*
- * Check if the image section header fits into the file. Knowing that at
- * least one section header follows we only need to check for the length
- * of the 64bit header which is longer than the 32bit header.
- */
- if (efi_size < dos->e_lfanew + sizeof(IMAGE_NT_HEADERS64)) {
- log_err("Invalid offset for Extended Header\n");
- ret = EFI_LOAD_ERROR;
- goto err;
- }
-
- nt = (void *) ((char *)efi + dos->e_lfanew);
- if (nt->Signature != IMAGE_NT_SIGNATURE) {
- log_err("Invalid NT Signature\n");
- ret = EFI_LOAD_ERROR;
- goto err;
+ ret = efi_check_pe(efi, efi_size, (void **)&nt);
+ if (ret != EFI_SUCCESS) {
+ log_err("Not a PE-COFF file\n");
+ return EFI_LOAD_ERROR;
}
for (i = 0; machines[i]; i++)
@@ -746,8 +760,7 @@ efi_status_t efi_load_pe(struct efi_loaded_image_obj *handle,
if (!supported) {
log_err("Machine type 0x%04x is not supported\n",
nt->FileHeader.Machine);
- ret = EFI_LOAD_ERROR;
- goto err;
+ return EFI_LOAD_ERROR;
}
num_sections = nt->FileHeader.NumberOfSections;
@@ -757,8 +770,7 @@ efi_status_t efi_load_pe(struct efi_loaded_image_obj *handle,
if (efi_size < ((void *)sections + sizeof(sections[0]) * num_sections
- efi)) {
log_err("Invalid number of sections: %d\n", num_sections);
- ret = EFI_LOAD_ERROR;
- goto err;
+ return EFI_LOAD_ERROR;
}
/* Authenticate an image */
diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c
index 11e755363e..a3106aba7f 100644
--- a/lib/efi_loader/efi_memory.c
+++ b/lib/efi_loader/efi_memory.c
@@ -541,8 +541,6 @@ efi_status_t efi_free_pages(uint64_t memory, efi_uintn_t pages)
ret = efi_add_memory_map_pg(memory, pages, EFI_CONVENTIONAL_MEMORY,
false);
- /* Merging of adjacent free regions is missing */
-
if (ret != EFI_SUCCESS)
return EFI_NOT_FOUND;
diff --git a/lib/efi_loader/efi_root_node.c b/lib/efi_loader/efi_root_node.c
index b17db312f7..b411a12cf6 100644
--- a/lib/efi_loader/efi_root_node.c
+++ b/lib/efi_loader/efi_root_node.c
@@ -7,6 +7,7 @@
#include <common.h>
#include <malloc.h>
+#include <efi_dt_fixup.h>
#include <efi_loader.h>
const efi_guid_t efi_u_boot_guid = U_BOOT_GUID;
@@ -60,6 +61,11 @@ efi_status_t efi_root_node_register(void)
/* Device path utilities protocol */
&efi_guid_device_path_utilities_protocol,
(void *)&efi_device_path_utilities,
+#if !CONFIG_IS_ENABLED(GENERATE_ACPI_TABLE)
+ /* Device-tree fix-up protocol */
+ &efi_guid_dt_fixup_protocol,
+ (void *)&efi_dt_fixup_prot,
+#endif
#if CONFIG_IS_ENABLED(EFI_UNICODE_COLLATION_PROTOCOL2)
#if CONFIG_IS_ENABLED(EFI_UNICODE_COLLATION_PROTOCOL)
/* Deprecated Unicode collation protocol */
diff --git a/lib/efi_loader/helloworld.c b/lib/efi_loader/helloworld.c
index 9ae2ee3389..5c8b7a96f9 100644
--- a/lib/efi_loader/helloworld.c
+++ b/lib/efi_loader/helloworld.c
@@ -1,43 +1,41 @@
// SPDX-License-Identifier: GPL-2.0+
/*
- * EFI hello world
+ * Hello world EFI application
*
- * Copyright (c) 2016 Google, Inc
- * Written by Simon Glass <sjg@chromium.org>
+ * Copyright 2020, Heinrich Schuchardt <xypron.glpk@gmx.de>
*
- * This program demonstrates calling a boottime service.
- * It writes a greeting and the load options to the console.
+ * This test program is used to test the invocation of an EFI application.
+ * It writes
+ *
+ * * a greeting
+ * * the firmware's UEFI version
+ * * the installed configuration tables
+ * * the boot device's device path and the file path
+ *
+ * to the console.
*/
-#include <common.h>
#include <efi_api.h>
static const efi_guid_t loaded_image_guid = EFI_LOADED_IMAGE_PROTOCOL_GUID;
+static const efi_guid_t device_path_to_text_protocol_guid =
+ EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID;
+static const efi_guid_t device_path_guid = EFI_DEVICE_PATH_PROTOCOL_GUID;
static const efi_guid_t fdt_guid = EFI_FDT_GUID;
static const efi_guid_t acpi_guid = EFI_ACPI_TABLE_GUID;
static const efi_guid_t smbios_guid = SMBIOS_TABLE_GUID;
+static struct efi_system_table *systable;
+static struct efi_boot_services *boottime;
+static struct efi_simple_text_output_protocol *con_out;
+
/**
- * efi_main() - entry point of the EFI application.
- *
- * @handle: handle of the loaded image
- * @systable: system table
- * @return: status code
+ * print_uefi_revision() - print UEFI revision number
*/
-efi_status_t EFIAPI efi_main(efi_handle_t handle,
- struct efi_system_table *systable)
+static void print_uefi_revision(void)
{
- struct efi_simple_text_output_protocol *con_out = systable->con_out;
- struct efi_boot_services *boottime = systable->boottime;
- struct efi_loaded_image *loaded_image;
- efi_status_t ret;
- efi_uintn_t i;
u16 rev[] = L"0.0.0";
- /* UEFI requires CR LF */
- con_out->output_string(con_out, L"Hello, world!\r\n");
-
- /* Print the revision number */
rev[0] = (systable->hdr.revision >> 16) + '0';
rev[4] = systable->hdr.revision & 0xffff;
for (; rev[4] >= 10;) {
@@ -53,15 +51,15 @@ efi_status_t EFIAPI efi_main(efi_handle_t handle,
con_out->output_string(con_out, L"Running on UEFI ");
con_out->output_string(con_out, rev);
con_out->output_string(con_out, L"\r\n");
+}
+
+/**
+ * print_config_tables() - print configuration tables
+ */
+static void print_config_tables(void)
+{
+ efi_uintn_t i;
- /* Get the loaded image protocol */
- ret = boottime->handle_protocol(handle, &loaded_image_guid,
- (void **)&loaded_image);
- if (ret != EFI_SUCCESS) {
- con_out->output_string
- (con_out, L"Cannot open loaded image protocol\r\n");
- goto out;
- }
/* Find configuration tables */
for (i = 0; i < systable->nr_tables; ++i) {
if (!memcmp(&systable->tables[i].guid, &fdt_guid,
@@ -77,6 +75,16 @@ efi_status_t EFIAPI efi_main(efi_handle_t handle,
con_out->output_string
(con_out, L"Have SMBIOS table\r\n");
}
+}
+
+/**
+ * print_load_options() - print load options
+ *
+ * @systable: system table
+ * @con_out: simple text output protocol
+ */
+void print_load_options(struct efi_loaded_image *loaded_image)
+{
/* Output the load options */
con_out->output_string(con_out, L"Load options: ");
if (loaded_image->load_options_size && loaded_image->load_options)
@@ -85,6 +93,105 @@ efi_status_t EFIAPI efi_main(efi_handle_t handle,
else
con_out->output_string(con_out, L"<none>");
con_out->output_string(con_out, L"\r\n");
+}
+
+/**
+ * print_device_path() - print device path
+ *
+ * @device_path: device path to print
+ * @dp2txt: device path to text protocol
+ */
+efi_status_t print_device_path(struct efi_device_path *device_path,
+ struct efi_device_path_to_text_protocol *dp2txt)
+{
+ u16 *string;
+ efi_status_t ret;
+
+ if (!device_path) {
+ con_out->output_string(con_out, L"<none>\r\n");
+ return EFI_SUCCESS;
+ }
+
+ string = dp2txt->convert_device_path_to_text(device_path, true, false);
+ if (!string) {
+ con_out->output_string
+ (con_out, L"Cannot convert device path to text\r\n");
+ return EFI_OUT_OF_RESOURCES;
+ }
+ con_out->output_string(con_out, string);
+ con_out->output_string(con_out, L"\r\n");
+ ret = boottime->free_pool(string);
+ if (ret != EFI_SUCCESS) {
+ con_out->output_string(con_out, L"Cannot free pool memory\r\n");
+ return ret;
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ * efi_main() - entry point of the EFI application.
+ *
+ * @handle: handle of the loaded image
+ * @systab: system table
+ * @return: status code
+ */
+efi_status_t EFIAPI efi_main(efi_handle_t handle,
+ struct efi_system_table *systab)
+{
+ struct efi_loaded_image *loaded_image;
+ struct efi_device_path_to_text_protocol *device_path_to_text;
+ struct efi_device_path *device_path;
+ efi_status_t ret;
+
+ systable = systab;
+ boottime = systable->boottime;
+ con_out = systable->con_out;
+
+ /* UEFI requires CR LF */
+ con_out->output_string(con_out, L"Hello, world!\r\n");
+
+ print_uefi_revision();
+ print_config_tables();
+
+ /* Get the loaded image protocol */
+ ret = boottime->handle_protocol(handle, &loaded_image_guid,
+ (void **)&loaded_image);
+ if (ret != EFI_SUCCESS) {
+ con_out->output_string
+ (con_out, L"Cannot open loaded image protocol\r\n");
+ goto out;
+ }
+ print_load_options(loaded_image);
+
+ /* Get the device path to text protocol */
+ ret = boottime->locate_protocol(&device_path_to_text_protocol_guid,
+ NULL, (void **)&device_path_to_text);
+ if (ret != EFI_SUCCESS) {
+ con_out->output_string
+ (con_out, L"Cannot open device path to text protocol\r\n");
+ goto out;
+ }
+ if (!loaded_image->device_handle) {
+ con_out->output_string
+ (con_out, L"Missing device handle\r\n");
+ goto out;
+ }
+ ret = boottime->handle_protocol(loaded_image->device_handle,
+ &device_path_guid,
+ (void **)&device_path);
+ if (ret != EFI_SUCCESS) {
+ con_out->output_string
+ (con_out, L"Missing devide path for device handle\r\n");
+ goto out;
+ }
+ con_out->output_string(con_out, L"Boot device: ");
+ ret = print_device_path(device_path, device_path_to_text);
+ if (ret != EFI_SUCCESS)
+ goto out;
+ con_out->output_string(con_out, L"File path: ");
+ ret = print_device_path(loaded_image->file_path, device_path_to_text);
+ if (ret != EFI_SUCCESS)
+ goto out;
out:
boottime->exit(handle, ret, 0, NULL);
diff --git a/lib/efi_selftest/dtbdump.c b/lib/efi_selftest/dtbdump.c
index d90e3eb768..efef759863 100644
--- a/lib/efi_selftest/dtbdump.c
+++ b/lib/efi_selftest/dtbdump.c
@@ -8,10 +8,12 @@
#include <common.h>
#include <efi_api.h>
+#include <efi_dt_fixup.h>
#define BUFFER_SIZE 64
#define ESC 0x17
-#define DEFAULT_FILENAME L"dtb.dtb"
+
+#define efi_size_in_pages(size) ((size + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT)
static struct efi_simple_text_output_protocol *cerr;
static struct efi_simple_text_output_protocol *cout;
@@ -21,6 +23,22 @@ static const efi_guid_t fdt_guid = EFI_FDT_GUID;
static const efi_guid_t loaded_image_guid = EFI_LOADED_IMAGE_PROTOCOL_GUID;
static const efi_guid_t guid_simple_file_system_protocol =
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID;
+static efi_handle_t handle;
+static struct efi_system_table *systable;
+static const efi_guid_t efi_dt_fixup_protocol_guid = EFI_DT_FIXUP_PROTOCOL_GUID;
+static const efi_guid_t efi_file_info_guid = EFI_FILE_INFO_GUID;
+
+/**
+ * error() - print error string
+ *
+ * @string: error text
+ */
+static void error(u16 *string)
+{
+ cout->set_attribute(cout, EFI_LIGHTRED | EFI_BACKGROUND_BLACK);
+ cout->output_string(cout, string);
+ cout->set_attribute(cout, EFI_LIGHTBLUE | EFI_BACKGROUND_BLACK);
+}
/**
* input() - read string from console
@@ -39,6 +57,7 @@ static efi_status_t efi_input(u16 *buffer, efi_uintn_t buffer_size)
/* Drain the console input */
ret = cin->reset(cin, true);
+ *buffer = 0;
for (;;) {
ret = bs->wait_for_event(1, &cin->wait_for_key, &index);
if (ret != EFI_SUCCESS)
@@ -62,6 +81,7 @@ static efi_status_t efi_input(u16 *buffer, efi_uintn_t buffer_size)
break;
case 0x0a: /* Linefeed */
case 0x0d: /* Carriage return */
+ cout->output_string(cout, L"\n");
return EFI_SUCCESS;
default:
break;
@@ -73,6 +93,7 @@ static efi_status_t efi_input(u16 *buffer, efi_uintn_t buffer_size)
pos < buffer_size - 1) {
*outbuf = key.unicode_char;
buffer[pos++] = key.unicode_char;
+ buffer[pos] = 0;
cout->output_string(cout, outbuf);
}
}
@@ -117,60 +138,228 @@ void *get_dtb(struct efi_system_table *systable)
}
/**
- * efi_main() - entry point of the EFI application.
+ * skip_whitespace() - skip over leading whitespace
*
- * @handle: handle of the loaded image
- * @systable: system table
- * @return: status code
+ * @pos: UTF-16 string
+ * Return: pointer to first non-whitespace
*/
-efi_status_t EFIAPI efi_main(efi_handle_t handle,
- struct efi_system_table *systable)
+u16 *skip_whitespace(u16 *pos)
{
- efi_uintn_t ret;
- u16 filename[BUFFER_SIZE] = {0};
- efi_uintn_t dtb_size;
+ for (; *pos && *pos <= 0x20; ++pos)
+ ;
+ return pos;
+}
+
+/**
+ * starts_with() - check if @string starts with @keyword
+ *
+ * @string: string to search for keyword
+ * @keyword: keyword to be searched
+ * Return: true fi @string starts with the keyword
+ */
+bool starts_with(u16 *string, u16 *keyword)
+{
+ for (; *keyword; ++string, ++keyword) {
+ if (*string != *keyword)
+ return false;
+ }
+ return true;
+}
+
+/**
+ * do_help() - print help
+ */
+void do_help(void)
+{
+ error(L"load <dtb> - load device-tree from file\n");
+ error(L"save <dtb> - save device-tree to file\n");
+ error(L"exit - exit the shell\n");
+}
+
+/**
+ * do_load() - load and install device-tree
+ *
+ * @filename: file name
+ * Return: status code
+ */
+efi_status_t do_load(u16 *filename)
+{
+ struct efi_dt_fixup_protocol *dt_fixup_prot;
struct efi_loaded_image *loaded_image;
struct efi_simple_file_system_protocol *file_system;
- struct efi_file_handle *root, *file;
+ struct efi_file_handle *root = NULL, *file = NULL;
+ u64 addr = 0;
+ struct efi_file_info *info;
struct fdt_header *dtb;
+ efi_uintn_t buffer_size;
+ efi_uintn_t pages;
+ efi_status_t ret, ret2;
- cerr = systable->std_err;
- cout = systable->con_out;
- cin = systable->con_in;
- bs = systable->boottime;
+ ret = bs->locate_protocol(&efi_dt_fixup_protocol_guid, NULL,
+ (void **)&dt_fixup_prot);
+ if (ret != EFI_SUCCESS) {
+ error(L"Device-tree fix-up protocol not found\n");
+ return ret;
+ }
- cout->set_attribute(cout, EFI_LIGHTGRAY | EFI_BACKGROUND_BLACK);
- cout->clear_screen(cout);
- cout->set_attribute(cout, EFI_YELLOW | EFI_BACKGROUND_BLACK);
- cout->output_string(cout, L"DTB Dump\n\n");
- cout->set_attribute(cout, EFI_LIGHTGRAY | EFI_BACKGROUND_BLACK);
+ filename = skip_whitespace(filename);
+
+ ret = bs->open_protocol(handle, &loaded_image_guid,
+ (void **)&loaded_image, NULL, NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (ret != EFI_SUCCESS) {
+ error(L"Loaded image protocol not found\n");
+ return ret;
+ }
+ /* Open the simple file system protocol */
+ ret = bs->open_protocol(loaded_image->device_handle,
+ &guid_simple_file_system_protocol,
+ (void **)&file_system, NULL, NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (ret != EFI_SUCCESS) {
+ error(L"Failed to open simple file system protocol\n");
+ goto out;
+ }
+
+ /* Open volume */
+ ret = file_system->open_volume(file_system, &root);
+ if (ret != EFI_SUCCESS) {
+ error(L"Failed to open volume\n");
+ goto out;
+ }
+
+ /* Open file */
+ ret = root->open(root, &file, filename, EFI_FILE_MODE_READ, 0);
+ if (ret != EFI_SUCCESS) {
+ error(L"File not found\n");
+ goto out;
+ }
+ /* Get file size */
+ buffer_size = 0;
+ ret = file->getinfo(file, &efi_file_info_guid, &buffer_size, NULL);
+ if (ret != EFI_BUFFER_TOO_SMALL) {
+ error(L"Can't get file info size\n");
+ goto out;
+ }
+ ret = bs->allocate_pool(EFI_LOADER_DATA, buffer_size, (void **)&info);
+ if (ret != EFI_SUCCESS) {
+ error(L"Out of memory\n");
+ goto out;
+ }
+ ret = file->getinfo(file, &efi_file_info_guid, &buffer_size, info);
+ if (ret != EFI_SUCCESS) {
+ error(L"Can't get file info\n");
+ goto out;
+ }
+ buffer_size = info->file_size;
+ pages = efi_size_in_pages(buffer_size);
+ ret = bs->free_pool(info);
+ if (ret != EFI_SUCCESS)
+ error(L"Can't free memory pool\n");
+ /* Read file */
+ ret = bs->allocate_pages(EFI_ALLOCATE_ANY_PAGES,
+ EFI_ACPI_RECLAIM_MEMORY,
+ pages, &addr);
+ if (ret != EFI_SUCCESS) {
+ error(L"Out of memory\n");
+ goto out;
+ }
+ dtb = (struct fdt_header *)(uintptr_t)addr;
+ ret = file->read(file, &buffer_size, dtb);
+ if (ret != EFI_SUCCESS) {
+ error(L"Can't read file\n");
+ goto out;
+ }
+ /* Fixup file, expecting EFI_BUFFER_TOO_SMALL */
+ ret = dt_fixup_prot->fixup(dt_fixup_prot, dtb, &buffer_size,
+ EFI_DT_APPLY_FIXUPS | EFI_DT_RESERVE_MEMORY |
+ EFI_DT_INSTALL_TABLE);
+ if (ret == EFI_BUFFER_TOO_SMALL) {
+ /* Read file into larger buffer */
+ ret = bs->free_pages(addr, pages);
+ if (ret != EFI_SUCCESS)
+ error(L"Can't free memory pages\n");
+ pages = efi_size_in_pages(buffer_size);
+ ret = bs->allocate_pages(EFI_ALLOCATE_ANY_PAGES,
+ EFI_ACPI_RECLAIM_MEMORY,
+ pages, &addr);
+ if (ret != EFI_SUCCESS) {
+ error(L"Out of memory\n");
+ goto out;
+ }
+ dtb = (struct fdt_header *)(uintptr_t)addr;
+ ret = file->setpos(file, 0);
+ if (ret != EFI_SUCCESS) {
+ error(L"Can't position file\n");
+ goto out;
+ }
+ ret = file->read(file, &buffer_size, dtb);
+ if (ret != EFI_SUCCESS) {
+ error(L"Can't read file\n");
+ goto out;
+ }
+ buffer_size = pages << EFI_PAGE_SHIFT;
+ ret = dt_fixup_prot->fixup(
+ dt_fixup_prot, dtb, &buffer_size,
+ EFI_DT_APPLY_FIXUPS | EFI_DT_RESERVE_MEMORY |
+ EFI_DT_INSTALL_TABLE);
+ }
+ if (ret == EFI_SUCCESS)
+ cout->output_string(cout, L"device-tree installed\n");
+ else
+ error(L"Device-tree fix-up failed\n");
+out:
+ if (addr) {
+ ret2 = bs->free_pages(addr, pages);
+ if (ret2 != EFI_SUCCESS)
+ error(L"Can't free memory pages\n");
+ }
+ if (file) {
+ ret2 = file->close(file);
+ if (ret2 != EFI_SUCCESS)
+ error(L"Can't close file\n");
+ }
+ if (root) {
+ ret2 = root->close(root);
+ if (ret2 != EFI_SUCCESS)
+ error(L"Can't close volume\n");
+ }
+ return ret;
+}
+
+/**
+ * do_save() - save current device-tree
+ *
+ * @filename: file name
+ * Return: status code
+ */
+efi_status_t do_save(u16 *filename)
+{
+ struct efi_loaded_image *loaded_image;
+ struct efi_simple_file_system_protocol *file_system;
+ efi_uintn_t dtb_size;
+ struct efi_file_handle *root, *file;
+ struct fdt_header *dtb;
+ efi_uintn_t ret;
dtb = get_dtb(systable);
if (!dtb) {
- cerr->output_string(cout, L"DTB not found\n");
+ error(L"DTB not found\n");
return EFI_NOT_FOUND;
}
if (f2h(dtb->magic) != FDT_MAGIC) {
- cerr->output_string(cout, L"Wrong device tree magic\n");
+ error(L"Wrong device tree magic\n");
return EFI_NOT_FOUND;
}
dtb_size = f2h(dtb->totalsize);
- cout->output_string(cout, L"Filename (" DEFAULT_FILENAME ")?\n");
- ret = efi_input(filename, sizeof(filename));
- if (ret != EFI_SUCCESS)
- return ret;
- if (!*filename)
- memcpy(filename, DEFAULT_FILENAME, sizeof(DEFAULT_FILENAME));
-
- cout->output_string(cout, L"\n");
+ filename = skip_whitespace(filename);
ret = bs->open_protocol(handle, &loaded_image_guid,
(void **)&loaded_image, NULL, NULL,
EFI_OPEN_PROTOCOL_GET_PROTOCOL);
if (ret != EFI_SUCCESS) {
- cerr->output_string(cout,
- L"Loaded image protocol not found\n");
+ error(L"Loaded image protocol not found\n");
return ret;
}
@@ -180,15 +369,14 @@ efi_status_t EFIAPI efi_main(efi_handle_t handle,
(void **)&file_system, NULL, NULL,
EFI_OPEN_PROTOCOL_GET_PROTOCOL);
if (ret != EFI_SUCCESS) {
- cerr->output_string(
- cout, L"Failed to open simple file system protocol\n");
+ error(L"Failed to open simple file system protocol\n");
return ret;
}
/* Open volume */
ret = file_system->open_volume(file_system, &root);
if (ret != EFI_SUCCESS) {
- cerr->output_string(cerr, L"Failed to open volume\n");
+ error(L"Failed to open volume\n");
return ret;
}
/* Create file */
@@ -199,10 +387,10 @@ efi_status_t EFIAPI efi_main(efi_handle_t handle,
/* Write file */
ret = file->write(file, &dtb_size, dtb);
if (ret != EFI_SUCCESS)
- cerr->output_string(cerr, L"Failed to write file\n");
+ error(L"Failed to write file\n");
file->close(file);
} else {
- cerr->output_string(cerr, L"Failed to open file\n");
+ error(L"Failed to open file\n");
}
root->close(root);
@@ -213,3 +401,51 @@ efi_status_t EFIAPI efi_main(efi_handle_t handle,
return ret;
}
+
+/**
+ * efi_main() - entry point of the EFI application.
+ *
+ * @handle: handle of the loaded image
+ * @systab: system table
+ * @return: status code
+ */
+efi_status_t EFIAPI efi_main(efi_handle_t image_handle,
+ struct efi_system_table *systab)
+{
+ handle = image_handle;
+ systable = systab;
+ cerr = systable->std_err;
+ cout = systable->con_out;
+ cin = systable->con_in;
+ bs = systable->boottime;
+
+ cout->set_attribute(cout, EFI_LIGHTBLUE | EFI_BACKGROUND_BLACK);
+ cout->clear_screen(cout);
+ cout->set_attribute(cout, EFI_WHITE | EFI_BACKGROUND_BLACK);
+ cout->output_string(cout, L"DTB Dump\n========\n\n");
+ cout->set_attribute(cout, EFI_LIGHTBLUE | EFI_BACKGROUND_BLACK);
+
+ for (;;) {
+ u16 command[BUFFER_SIZE];
+ u16 *pos;
+ efi_uintn_t ret;
+
+ cout->output_string(cout, L"=> ");
+ ret = efi_input(command, sizeof(command));
+ if (ret == EFI_ABORTED)
+ break;
+ pos = skip_whitespace(command);
+ if (starts_with(pos, L"exit"))
+ break;
+ else if (starts_with(pos, L"load "))
+ do_load(pos + 5);
+ else if (starts_with(pos, L"save "))
+ do_save(pos + 5);
+ else
+ do_help();
+ }
+
+ cout->set_attribute(cout, EFI_LIGHTGRAY | EFI_BACKGROUND_BLACK);
+ cout->clear_screen(cout);
+ return EFI_SUCCESS;
+}