From e2dc4229ad009df13b131fcc16516e79c14276b7 Mon Sep 17 00:00:00 2001 From: Ivan Gorinov Date: Wed, 2 May 2018 16:36:02 -0700 Subject: [PATCH 01/36] efi_loader: correctly apply relocations from the .reloc section Instead of difference between preferred and actual image base, the actual base is added to the fields specified in the .reloc section. Use ImageBase from PE optional header to compute the delta, exit early if the image is loaded at the preferred address. Signed-off-by: Ivan Gorinov Reviewed-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- lib/efi_loader/efi_image_loader.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/lib/efi_loader/efi_image_loader.c b/lib/efi_loader/efi_image_loader.c index b45f09591a5..e702afd87c1 100644 --- a/lib/efi_loader/efi_image_loader.c +++ b/lib/efi_loader/efi_image_loader.c @@ -90,11 +90,16 @@ void efi_print_image_infos(void *pc) } static efi_status_t efi_loader_relocate(const IMAGE_BASE_RELOCATION *rel, - unsigned long rel_size, void *efi_reloc) + unsigned long rel_size, void *efi_reloc, + unsigned long pref_address) { + unsigned long delta = (unsigned long)efi_reloc - pref_address; const IMAGE_BASE_RELOCATION *end; int i; + if (delta == 0) + return EFI_SUCCESS; + end = (const IMAGE_BASE_RELOCATION *)((const char *)rel + rel_size); while (rel < end - 1 && rel->SizeOfBlock) { const uint16_t *relocs = (const uint16_t *)(rel + 1); @@ -103,7 +108,6 @@ static efi_status_t efi_loader_relocate(const IMAGE_BASE_RELOCATION *rel, uint32_t offset = (uint32_t)(*relocs & 0xfff) + rel->VirtualAddress; int type = *relocs >> EFI_PAGE_SHIFT; - unsigned long delta = (unsigned long)efi_reloc; uint64_t *x64 = efi_reloc + offset; uint32_t *x32 = efi_reloc + offset; uint16_t *x16 = efi_reloc + offset; @@ -191,6 +195,7 @@ void *efi_load_pe(void *efi, struct efi_loaded_image *loaded_image_info) unsigned long rel_size; int rel_idx = IMAGE_DIRECTORY_ENTRY_BASERELOC; void *entry; + uint64_t image_base; uint64_t image_size; unsigned long virt_size = 0; int supported = 0; @@ -234,6 +239,7 @@ void *efi_load_pe(void *efi, struct efi_loaded_image *loaded_image_info) if (nt->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) { IMAGE_NT_HEADERS64 *nt64 = (void *)nt; IMAGE_OPTIONAL_HEADER64 *opt = &nt64->OptionalHeader; + image_base = opt->ImageBase; image_size = opt->SizeOfImage; efi_set_code_and_data_type(loaded_image_info, opt->Subsystem); efi_reloc = efi_alloc(virt_size, @@ -249,6 +255,7 @@ void *efi_load_pe(void *efi, struct efi_loaded_image *loaded_image_info) virt_size = ALIGN(virt_size, opt->SectionAlignment); } else if (nt->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) { IMAGE_OPTIONAL_HEADER32 *opt = &nt->OptionalHeader; + image_base = opt->ImageBase; image_size = opt->SizeOfImage; efi_set_code_and_data_type(loaded_image_info, opt->Subsystem); efi_reloc = efi_alloc(virt_size, @@ -279,7 +286,8 @@ void *efi_load_pe(void *efi, struct efi_loaded_image *loaded_image_info) } /* Run through relocations */ - if (efi_loader_relocate(rel, rel_size, efi_reloc) != EFI_SUCCESS) { + if (efi_loader_relocate(rel, rel_size, efi_reloc, + (unsigned long)image_base) != EFI_SUCCESS) { efi_free_pages((uintptr_t) efi_reloc, (virt_size + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT); return NULL; From 503e04fab85c0ae0603758693d135bb2576e529b Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 29 Apr 2018 23:37:12 +0200 Subject: [PATCH 02/36] efi_loader: if EFI_LOADER is enabled, enable CFB_CONSOLE_ANSI EFI applications like GRUB issue ANSI sequences for setting colors and for positioning. So if the EFI subsystem is enabled, we should also enable ANSI control sequences by default. Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- lib/efi_loader/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig index 2909e769608..df58e633d1c 100644 --- a/lib/efi_loader/Kconfig +++ b/lib/efi_loader/Kconfig @@ -10,6 +10,7 @@ config EFI_LOADER default y select LIB_UUID select HAVE_BLOCK_DEVICE + imply CFB_CONSOLE_ANSI help Select this option if you want to run EFI applications (like grub2) on top of U-Boot. If this option is enabled, U-Boot will expose EFI From 1f0532ca15aa8fafa1e133e6b5ce8d0bf08fac46 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Fri, 27 Apr 2018 19:07:24 +0200 Subject: [PATCH 03/36] efi_loader: remove unnecessary include asm/global_data.h is already included via common.h. Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- lib/efi_loader/efi_boottime.c | 1 - lib/efi_loader/efi_image_loader.c | 1 - lib/efi_loader/efi_memory.c | 1 - lib/efi_loader/efi_runtime.c | 1 - 4 files changed, 4 deletions(-) diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index 5715a8b810e..862ba117282 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include diff --git a/lib/efi_loader/efi_image_loader.c b/lib/efi_loader/efi_image_loader.c index e702afd87c1..3cffe9ef461 100644 --- a/lib/efi_loader/efi_image_loader.c +++ b/lib/efi_loader/efi_image_loader.c @@ -10,7 +10,6 @@ #include #include #include -#include const efi_guid_t efi_global_variable_guid = EFI_GLOBAL_VARIABLE_GUID; const efi_guid_t efi_guid_device_path = DEVICE_PATH_GUID; diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c index 664c651db56..d3302b66498 100644 --- a/lib/efi_loader/efi_memory.c +++ b/lib/efi_loader/efi_memory.c @@ -10,7 +10,6 @@ #include #include #include -#include #include DECLARE_GLOBAL_DATA_PTR; diff --git a/lib/efi_loader/efi_runtime.c b/lib/efi_loader/efi_runtime.c index 241090f6b48..e027f47a93e 100644 --- a/lib/efi_loader/efi_runtime.c +++ b/lib/efi_loader/efi_runtime.c @@ -10,7 +10,6 @@ #include #include #include -#include /* For manual relocation support */ DECLARE_GLOBAL_DATA_PTR; From 7ca7c3c0f927b91dad3a5b2d185fe79d12872b6d Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 29 Apr 2018 16:24:25 +0200 Subject: [PATCH 04/36] efi_loader: updating the cursor position The current coding advances the column by the number of UTF-8 bytes. The column should be increased by one per unicode character. The UEFI spec provides advance rules for U+0000, U+0008, U+000A, and U000D. All other characters, including control characters U+0007 (bel) and U+0009 (tab), have to increase the column by one. Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- lib/efi_loader/efi_console.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/lib/efi_loader/efi_console.c b/lib/efi_loader/efi_console.c index d777db8a3ed..10fb224901a 100644 --- a/lib/efi_loader/efi_console.c +++ b/lib/efi_loader/efi_console.c @@ -116,25 +116,36 @@ static efi_status_t EFIAPI efi_cout_output_string( unsigned int n16 = utf16_strlen(string); char buf[MAX_UTF8_PER_UTF16 * n16 + 1]; - char *p; + u16 *p; *utf16_to_utf8((u8 *)buf, string, n16) = '\0'; fputs(stdout, buf); - for (p = buf; *p; p++) { + /* + * Update the cursor position. + * + * The UEFI spec provides advance rules for U+0000, U+0008, U+000A, + * and U000D. All other characters, including control characters + * U+0007 (bel) and U+0009 (tab), have to increase the column by one. + */ + for (p = string; *p; ++p) { switch (*p) { - case '\r': /* carriage-return */ - con->cursor_column = 0; + case '\b': /* U+0008, backspace */ + con->cursor_column = max(0, con->cursor_column - 1); break; - case '\n': /* newline */ + case '\n': /* U+000A, newline */ con->cursor_column = 0; con->cursor_row++; break; - case '\t': /* tab, assume 8 char align */ + case '\r': /* U+000D, carriage-return */ + con->cursor_column = 0; break; - case '\b': /* backspace */ - con->cursor_column = max(0, con->cursor_column - 1); + case 0xd800 ... 0xdbff: + /* + * Ignore high surrogates, we do not want to count a + * Unicode character twice. + */ break; default: con->cursor_column++; From f2431415d6ae920995a717b1e1bc3f57d53938b5 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 29 Apr 2018 16:24:26 +0200 Subject: [PATCH 05/36] efi_selftest: updating the cursor position The test case for text output is updated to check correct updating of the cursor position. Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- lib/efi_selftest/efi_selftest_textoutput.c | 78 ++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/lib/efi_selftest/efi_selftest_textoutput.c b/lib/efi_selftest/efi_selftest_textoutput.c index 3533647fd49..a87f65e197f 100644 --- a/lib/efi_selftest/efi_selftest_textoutput.c +++ b/lib/efi_selftest/efi_selftest_textoutput.c @@ -23,6 +23,13 @@ static int execute(void) size_t background; size_t attrib; efi_status_t ret; + s16 col; + u16 cr[] = { 0x0d, 0x00 }; + u16 lf[] = { 0x0a, 0x00 }; + u16 brahmi[] = { /* 2 Brahmi letters */ + 0xD804, 0xDC05, + 0xD804, 0xDC22, + 0}; /* SetAttribute */ efi_st_printf("\nColor palette\n"); @@ -42,6 +49,77 @@ static int execute(void) efi_st_error("TestString failed for ANSI characters\n"); return EFI_ST_FAILURE; } + /* OutputString */ + ret = con_out->output_string(con_out, + L"Testing cursor column update\n"); + if (ret != EFI_ST_SUCCESS) { + efi_st_error("OutputString failed for ANSI characters"); + return EFI_ST_FAILURE; + } + col = con_out->mode->cursor_column; + ret = con_out->output_string(con_out, lf); + if (ret != EFI_ST_SUCCESS) { + efi_st_error("OutputString failed for line feed\n"); + return EFI_ST_FAILURE; + } + if (con_out->mode->cursor_column != col) { + efi_st_error("Cursor column changed by line feed\n"); + return EFI_ST_FAILURE; + } + ret = con_out->output_string(con_out, cr); + if (ret != EFI_ST_SUCCESS) { + efi_st_error("OutputString failed for carriage return\n"); + return EFI_ST_FAILURE; + } + if (con_out->mode->cursor_column) { + efi_st_error("Cursor column not 0 at beginning of line\n"); + return EFI_ST_FAILURE; + } + ret = con_out->output_string(con_out, L"123"); + if (ret != EFI_ST_SUCCESS) { + efi_st_error("OutputString failed for ANSI characters\n"); + return EFI_ST_FAILURE; + } + if (con_out->mode->cursor_column != 3) { + efi_st_error("Cursor column not incremented properly\n"); + return EFI_ST_FAILURE; + } + ret = con_out->output_string(con_out, L"\b"); + if (ret != EFI_ST_SUCCESS) { + efi_st_error("OutputString failed for backspace\n"); + return EFI_ST_FAILURE; + } + if (con_out->mode->cursor_column != 2) { + efi_st_error("Cursor column not decremented properly\n"); + return EFI_ST_FAILURE; + } + ret = con_out->output_string(con_out, L"\b\b"); + if (ret != EFI_ST_SUCCESS) { + efi_st_error("OutputString failed for backspace\n"); + return EFI_ST_FAILURE; + } + if (con_out->mode->cursor_column) { + efi_st_error("Cursor column not decremented properly\n"); + return EFI_ST_FAILURE; + } + ret = con_out->output_string(con_out, L"\b\b"); + if (ret != EFI_ST_SUCCESS) { + efi_st_error("OutputString failed for backspace\n"); + return EFI_ST_FAILURE; + } + if (con_out->mode->cursor_column) { + efi_st_error("Cursor column decremented past zero\n"); + return EFI_ST_FAILURE; + } + ret = con_out->output_string(con_out, brahmi); + if (ret != EFI_ST_SUCCESS) { + efi_st_todo("Unicode output not fully supported\n"); + } else if (con_out->mode->cursor_column != 2) { + efi_st_printf("Unicode not handled properly\n"); + return EFI_ST_FAILURE; + } + efi_st_printf("\n"); + return EFI_ST_SUCCESS; } From a4aa7bef3c66e473ab4671b0edef1bb66488a032 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 29 Apr 2018 20:02:46 +0200 Subject: [PATCH 06/36] efi_loader: always check parameters in efi_cout_query_mode() If we cannot determine the size of the serial terminal we still have to check the parameters of efi_cout_query_mode(). Querying the size of the serial terminal drains the keyboard buffer. So make sure we do this during the initialization and not in the midst of an EFI application. Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- lib/efi_loader/efi_console.c | 90 +++++++++++++++++++----------------- 1 file changed, 48 insertions(+), 42 deletions(-) diff --git a/lib/efi_loader/efi_console.c b/lib/efi_loader/efi_console.c index 10fb224901a..c09b93d9d68 100644 --- a/lib/efi_loader/efi_console.c +++ b/lib/efi_loader/efi_console.c @@ -12,8 +12,6 @@ #include #include -static bool console_size_queried; - #define EFI_COUT_MODE_2 2 #define EFI_MAX_COUT_MODE 3 @@ -205,6 +203,51 @@ static int query_console_serial(int *rows, int *cols) return 0; } +/* + * Update the mode table. + * + * By default the only mode available is 80x25. If the console has at least 50 + * lines, enable mode 80x50. If we can query the console size and it is neither + * 80x25 nor 80x50, set it as an additional mode. + */ +static void query_console_size(void) +{ + const char *stdout_name = env_get("stdout"); + int rows, cols; + + if (stdout_name && !strcmp(stdout_name, "vidconsole") && + IS_ENABLED(CONFIG_DM_VIDEO)) { + struct stdio_dev *stdout_dev = + stdio_get_by_name("vidconsole"); + struct udevice *dev = stdout_dev->priv; + struct vidconsole_priv *priv = + dev_get_uclass_priv(dev); + rows = priv->rows; + cols = priv->cols; + } else if (query_console_serial(&rows, &cols)) { + return; + } + + /* Test if we can have Mode 1 */ + if (cols >= 80 && rows >= 50) { + efi_cout_modes[1].present = 1; + efi_con_mode.max_mode = 2; + } + + /* + * Install our mode as mode 2 if it is different + * than mode 0 or 1 and set it as the currently selected mode + */ + if (!cout_mode_matches(&efi_cout_modes[0], rows, cols) && + !cout_mode_matches(&efi_cout_modes[1], rows, cols)) { + efi_cout_modes[EFI_COUT_MODE_2].columns = cols; + efi_cout_modes[EFI_COUT_MODE_2].rows = rows; + efi_cout_modes[EFI_COUT_MODE_2].present = 1; + efi_con_mode.max_mode = EFI_MAX_COUT_MODE; + efi_con_mode.mode = EFI_COUT_MODE_2; + } +} + static efi_status_t EFIAPI efi_cout_query_mode( struct efi_simple_text_output_protocol *this, unsigned long mode_number, unsigned long *columns, @@ -212,52 +255,12 @@ static efi_status_t EFIAPI efi_cout_query_mode( { EFI_ENTRY("%p, %ld, %p, %p", this, mode_number, columns, rows); - if (!console_size_queried) { - const char *stdout_name = env_get("stdout"); - int rows, cols; - - console_size_queried = true; - - if (stdout_name && !strcmp(stdout_name, "vidconsole") && - IS_ENABLED(CONFIG_DM_VIDEO)) { - struct stdio_dev *stdout_dev = - stdio_get_by_name("vidconsole"); - struct udevice *dev = stdout_dev->priv; - struct vidconsole_priv *priv = - dev_get_uclass_priv(dev); - rows = priv->rows; - cols = priv->cols; - } else if (query_console_serial(&rows, &cols)) { - goto out; - } - - /* Test if we can have Mode 1 */ - if (cols >= 80 && rows >= 50) { - efi_cout_modes[1].present = 1; - efi_con_mode.max_mode = 2; - } - - /* - * Install our mode as mode 2 if it is different - * than mode 0 or 1 and set it as the currently selected mode - */ - if (!cout_mode_matches(&efi_cout_modes[0], rows, cols) && - !cout_mode_matches(&efi_cout_modes[1], rows, cols)) { - efi_cout_modes[EFI_COUT_MODE_2].columns = cols; - efi_cout_modes[EFI_COUT_MODE_2].rows = rows; - efi_cout_modes[EFI_COUT_MODE_2].present = 1; - efi_con_mode.max_mode = EFI_MAX_COUT_MODE; - efi_con_mode.mode = EFI_COUT_MODE_2; - } - } - if (mode_number >= efi_con_mode.max_mode) return EFI_EXIT(EFI_UNSUPPORTED); if (efi_cout_modes[mode_number].present != 1) return EFI_EXIT(EFI_UNSUPPORTED); -out: if (columns) *columns = efi_cout_modes[mode_number].columns; if (rows) @@ -565,6 +568,9 @@ int efi_console_register(void) struct efi_object *efi_console_output_obj; struct efi_object *efi_console_input_obj; + /* Set up mode information */ + query_console_size(); + /* Create handles */ r = efi_create_handle((efi_handle_t *)&efi_console_output_obj); if (r != EFI_SUCCESS) From 508d8567046fe3c0d1354fc3a7a6f81d9661a661 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Fri, 18 May 2018 19:12:19 +0200 Subject: [PATCH 07/36] efi_selftest: allow building relocation code on x86_64 Variables EFI_RELOC and EFI_CRT0 have to be defined to build the EFI unit tests. This patch ensures this for the x86 architecure. If we compile with EFI_STUB, the bitness depends on CONFIG_EFI_STUB_64BIT. Otherwise the bitness depends on CONFIG_X86_64. Signed-off-by: Heinrich Schuchardt Reviewed-by: Simon Glass Signed-off-by: Alexander Graf --- arch/x86/config.mk | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/arch/x86/config.mk b/arch/x86/config.mk index 97db03deeed..5f77f98e60a 100644 --- a/arch/x86/config.mk +++ b/arch/x86/config.mk @@ -86,9 +86,9 @@ else PLATFORM_CPPFLAGS += -D__I386__ endif -ifneq ($(CONFIG_EFI_STUB)$(CONFIG_CMD_BOOTEFI_HELLO_COMPILE),) +ifdef CONFIG_EFI_STUB -ifneq ($(CONFIG_EFI_STUB_64BIT),) +ifdef CONFIG_EFI_STUB_64BIT EFI_LDS := elf_x86_64_efi.lds EFI_CRT0 := crt0_x86_64_efi.o EFI_RELOC := reloc_x86_64_efi.o @@ -98,10 +98,22 @@ EFI_CRT0 := crt0_ia32_efi.o EFI_RELOC := reloc_ia32_efi.o endif +else + +ifdef CONFIG_X86_64 +EFI_LDS := elf_x86_64_efi.lds +EFI_CRT0 := crt0_x86_64_efi.o +EFI_RELOC := reloc_x86_64_efi.o +else +EFI_LDS := elf_ia32_efi.lds +EFI_CRT0 := crt0_ia32_efi.o +EFI_RELOC := reloc_ia32_efi.o +endif + +endif + ifdef CONFIG_X86_64 EFI_TARGET := --target=efi-app-x86_64 else EFI_TARGET := --target=efi-app-ia32 endif - -endif From f2560e2dea5d7ff2fa67b9996c5ce5e6bb644627 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Fri, 18 May 2018 19:12:20 +0200 Subject: [PATCH 08/36] efi_loader: build CRT0 and RELOC on x86_64 The efi selftest and the hello application require CRT0 and RELOC to be built. Signed-off-by: Heinrich Schuchardt Reviewed-by: Simon Glass Signed-off-by: Alexander Graf --- arch/x86/lib/Makefile | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile index 51d451f9522..5a64f6eddc7 100644 --- a/arch/x86/lib/Makefile +++ b/arch/x86/lib/Makefile @@ -68,8 +68,18 @@ extra-$(CONFIG_EFI_STUB_64BIT) += crt0_x86_64_efi.o reloc_x86_64_efi.o endif -ifneq ($(CONFIG_EFI_STUB)$(CONFIG_CMD_BOOTEFI_HELLO_COMPILE),) +ifdef CONFIG_EFI_STUB + ifeq ($(CONFIG_$(SPL_)X86_64),) extra-y += $(EFI_CRT0) $(EFI_RELOC) endif + +else + +ifndef CONFIG_SPL_BUILD +ifneq ($(CONFIG_CMD_BOOTEFI_SELFTEST)$(CONFIG_CMD_BOOTEFI_HELLO_COMPILE),) +extra-y += $(EFI_CRT0) $(EFI_RELOC) +endif +endif + endif From c2d9097ac9ca4f30e7f1a87af08d8fed644bb057 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Thu, 17 May 2018 18:57:13 +0200 Subject: [PATCH 09/36] Makefile: clean should delete *.efi Files *.efi are generated files. So the clean target should delete them. Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 2995a198910..1278cea71b1 100644 --- a/Makefile +++ b/Makefile @@ -1625,7 +1625,8 @@ clean: $(clean-dirs) -o -name '*.symtypes' -o -name 'modules.order' \ -o -name modules.builtin -o -name '.tmp_*.o.*' \ -o -name 'dsdt.aml' -o -name 'dsdt.asl.tmp' -o -name 'dsdt.c' \ - -o -name '*.gcno' \) -type f -print | xargs rm -f + -o -name '*.efi' -o -name '*.gcno' \) \ + -type f -print | xargs rm -f # mrproper - Delete all generated files, including .config # From e37aa7ada39f5291ce92f7d8bc2b66917fb5f8fa Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Thu, 17 May 2018 18:24:48 +0200 Subject: [PATCH 10/36] efi_selftest: do not call efi_init_obj_list() twice Remove a superfluous call to efi_init_obj_list() invoked by 'bootefi selftest'. Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- cmd/bootefi.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/cmd/bootefi.c b/cmd/bootefi.c index 11b84c55289..80491c77fd1 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -428,8 +428,6 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) * callback entry */ efi_save_gd(); - /* Initialize and populate EFI object list */ - efi_init_obj_list(); /* Transfer environment variable efi_selftest as load options */ set_load_options(&loaded_image_info, "efi_selftest"); /* Execute the test */ From 45c66f9cdfe40aee78c01ea3f4cdc9573b2c60ed Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Thu, 17 May 2018 07:57:05 +0200 Subject: [PATCH 11/36] efi_loader: adjust definitions of variable services The definitons of the variable services are adjusted: - use efi_uintn_t instead of unsigned long - use u16 * instead of s16 * for Unicode strings - correct definition of QueryVariableInfo - rename efi_get_next_variable to efi_get_next_variable_name Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- include/efi_api.h | 24 ++++++++++++------------ include/efi_loader.h | 18 +++++++++--------- lib/efi_loader/efi_bootmgr.c | 10 +++++----- lib/efi_loader/efi_runtime.c | 10 +++++----- lib/efi_loader/efi_variable.c | 24 ++++++++++++------------ 5 files changed, 43 insertions(+), 43 deletions(-) diff --git a/include/efi_api.h b/include/efi_api.h index 64c27e494bc..094be6edf9b 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -214,15 +214,15 @@ struct efi_runtime_services { uint32_t descriptor_version, struct efi_mem_desc *virtmap); efi_status_t (*convert_pointer)(unsigned long dbg, void **address); - efi_status_t (EFIAPI *get_variable)(s16 *variable_name, - efi_guid_t *vendor, u32 *attributes, - unsigned long *data_size, void *data); - efi_status_t (EFIAPI *get_next_variable)( - unsigned long *variable_name_size, - s16 *variable_name, efi_guid_t *vendor); - efi_status_t (EFIAPI *set_variable)(s16 *variable_name, - efi_guid_t *vendor, u32 attributes, - unsigned long data_size, void *data); + efi_status_t (EFIAPI *get_variable)(u16 *variable_name, + efi_guid_t *vendor, u32 *attributes, + efi_uintn_t *data_size, void *data); + efi_status_t (EFIAPI *get_next_variable_name)( + efi_uintn_t *variable_name_size, + u16 *variable_name, efi_guid_t *vendor); + efi_status_t (EFIAPI *set_variable)(u16 *variable_name, + efi_guid_t *vendor, u32 attributes, + efi_uintn_t data_size, void *data); efi_status_t (EFIAPI *get_next_high_mono_count)( uint32_t *high_count); void (EFIAPI *reset_system)(enum efi_reset_type reset_type, @@ -239,9 +239,9 @@ struct efi_runtime_services { u32 reset_type); efi_status_t (EFIAPI *query_variable_info)( u32 attributes, - u64 maximum_variable_storage_size, - u64 remaining_variable_storage_size, - u64 maximum_variable_size); + u64 *maximum_variable_storage_size, + u64 *remaining_variable_storage_size, + u64 *maximum_variable_size); }; /* EFI event group GUID definitions */ diff --git a/include/efi_loader.h b/include/efi_loader.h index ec000658f6d..0c286bf6bed 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -422,15 +422,15 @@ efi_status_t EFIAPI efi_selftest(efi_handle_t image_handle, struct efi_system_table *systab); #endif -efi_status_t EFIAPI efi_get_variable(s16 *variable_name, - efi_guid_t *vendor, u32 *attributes, - unsigned long *data_size, void *data); -efi_status_t EFIAPI efi_get_next_variable( - unsigned long *variable_name_size, - s16 *variable_name, efi_guid_t *vendor); -efi_status_t EFIAPI efi_set_variable(s16 *variable_name, - efi_guid_t *vendor, u32 attributes, - unsigned long data_size, void *data); +efi_status_t EFIAPI efi_get_variable(u16 *variable_name, efi_guid_t *vendor, + u32 *attributes, efi_uintn_t *data_size, + void *data); +efi_status_t EFIAPI efi_get_next_variable_name(efi_uintn_t *variable_name_size, + u16 *variable_name, + efi_guid_t *vendor); +efi_status_t EFIAPI efi_set_variable(u16 *variable_name, efi_guid_t *vendor, + u32 attributes, efi_uintn_t data_size, + void *data); void *efi_bootmgr_load(struct efi_device_path **device_path, struct efi_device_path **file_path); diff --git a/lib/efi_loader/efi_bootmgr.c b/lib/efi_loader/efi_bootmgr.c index 153e1737573..853358ab937 100644 --- a/lib/efi_loader/efi_bootmgr.c +++ b/lib/efi_loader/efi_bootmgr.c @@ -70,17 +70,17 @@ static void parse_load_option(struct load_option *lo, void *ptr) /* free() the result */ static void *get_var(u16 *name, const efi_guid_t *vendor, - unsigned long *size) + efi_uintn_t *size) { efi_guid_t *v = (efi_guid_t *)vendor; efi_status_t ret; void *buf = NULL; *size = 0; - EFI_CALL(ret = rs->get_variable((s16 *)name, v, NULL, size, buf)); + EFI_CALL(ret = rs->get_variable(name, v, NULL, size, buf)); if (ret == EFI_BUFFER_TOO_SMALL) { buf = malloc(*size); - EFI_CALL(ret = rs->get_variable((s16 *)name, v, NULL, size, buf)); + EFI_CALL(ret = rs->get_variable(name, v, NULL, size, buf)); } if (ret != EFI_SUCCESS) { @@ -104,7 +104,7 @@ static void *try_load_entry(uint16_t n, struct efi_device_path **device_path, u16 varname[] = L"Boot0000"; u16 hexmap[] = L"0123456789ABCDEF"; void *load_option, *image = NULL; - unsigned long size; + efi_uintn_t size; varname[4] = hexmap[(n & 0xf000) >> 12]; varname[5] = hexmap[(n & 0x0f00) >> 8]; @@ -147,7 +147,7 @@ void *efi_bootmgr_load(struct efi_device_path **device_path, struct efi_device_path **file_path) { uint16_t *bootorder; - unsigned long size; + efi_uintn_t size; void *image = NULL; int i, num; diff --git a/lib/efi_loader/efi_runtime.c b/lib/efi_loader/efi_runtime.c index e027f47a93e..65f2bcf1401 100644 --- a/lib/efi_loader/efi_runtime.c +++ b/lib/efi_loader/efi_runtime.c @@ -212,7 +212,7 @@ static const struct efi_runtime_detach_list_struct efi_runtime_detach_list[] = { .ptr = &efi_runtime_services.get_variable, .patchto = &efi_device_error, }, { - .ptr = &efi_runtime_services.get_next_variable, + .ptr = &efi_runtime_services.get_next_variable_name, .patchto = &efi_device_error, }, { .ptr = &efi_runtime_services.set_variable, @@ -444,9 +444,9 @@ efi_status_t __efi_runtime EFIAPI efi_query_capsule_caps( efi_status_t __efi_runtime EFIAPI efi_query_variable_info( u32 attributes, - u64 maximum_variable_storage_size, - u64 remaining_variable_storage_size, - u64 maximum_variable_size) + u64 *maximum_variable_storage_size, + u64 *remaining_variable_storage_size, + u64 *maximum_variable_size) { return EFI_UNSUPPORTED; } @@ -464,7 +464,7 @@ struct efi_runtime_services __efi_runtime_data efi_runtime_services = { .set_virtual_address_map = &efi_set_virtual_address_map, .convert_pointer = (void *)&efi_invalid_parameter, .get_variable = efi_get_variable, - .get_next_variable = efi_get_next_variable, + .get_next_variable_name = efi_get_next_variable_name, .set_variable = efi_set_variable, .get_next_high_mono_count = (void *)&efi_device_error, .reset_system = &efi_reset_system_boottime, diff --git a/lib/efi_loader/efi_variable.c b/lib/efi_loader/efi_variable.c index 7e0e7f020ee..64cf981cdc5 100644 --- a/lib/efi_loader/efi_variable.c +++ b/lib/efi_loader/efi_variable.c @@ -113,8 +113,8 @@ static char *mem2hex(char *hexstr, const u8 *mem, int count) return hexstr; } -static efi_status_t efi_to_native(char *native, s16 *variable_name, - efi_guid_t *vendor) +static efi_status_t efi_to_native(char *native, u16 *variable_name, + efi_guid_t *vendor) { size_t len; @@ -176,9 +176,9 @@ static const char *parse_attr(const char *str, u32 *attrp) } /* http://wiki.phoenix.com/wiki/index.php/EFI_RUNTIME_SERVICES#GetVariable.28.29 */ -efi_status_t EFIAPI efi_get_variable(s16 *variable_name, - efi_guid_t *vendor, u32 *attributes, - unsigned long *data_size, void *data) +efi_status_t EFIAPI efi_get_variable(u16 *variable_name, efi_guid_t *vendor, + u32 *attributes, efi_uintn_t *data_size, + void *data) { char native_name[MAX_NATIVE_VAR_NAME + 1]; efi_status_t ret; @@ -250,9 +250,9 @@ efi_status_t EFIAPI efi_get_variable(s16 *variable_name, } /* http://wiki.phoenix.com/wiki/index.php/EFI_RUNTIME_SERVICES#GetNextVariableName.28.29 */ -efi_status_t EFIAPI efi_get_next_variable( - unsigned long *variable_name_size, - s16 *variable_name, efi_guid_t *vendor) +efi_status_t EFIAPI efi_get_next_variable_name(efi_uintn_t *variable_name_size, + u16 *variable_name, + efi_guid_t *vendor) { EFI_ENTRY("%p \"%ls\" %pUl", variable_name_size, variable_name, vendor); @@ -260,16 +260,16 @@ efi_status_t EFIAPI efi_get_next_variable( } /* http://wiki.phoenix.com/wiki/index.php/EFI_RUNTIME_SERVICES#SetVariable.28.29 */ -efi_status_t EFIAPI efi_set_variable(s16 *variable_name, - efi_guid_t *vendor, u32 attributes, - unsigned long data_size, void *data) +efi_status_t EFIAPI efi_set_variable(u16 *variable_name, efi_guid_t *vendor, + u32 attributes, efi_uintn_t data_size, + void *data) { char native_name[MAX_NATIVE_VAR_NAME + 1]; efi_status_t ret = EFI_SUCCESS; char *val, *s; u32 attr; - EFI_ENTRY("\"%ls\" %pUl %x %lu %p", variable_name, vendor, attributes, + EFI_ENTRY("\"%ls\" %pUl %x %zu %p", variable_name, vendor, attributes, data_size, data); if (!variable_name || !vendor) From d799c67ad32e5bb1a7ae098611c2990f80099309 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Thu, 17 May 2018 07:57:06 +0200 Subject: [PATCH 12/36] efi_selftest: unit test for variable services Provide a unit test for variable services. Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- lib/efi_selftest/Makefile | 1 + lib/efi_selftest/efi_selftest_variables.c | 180 ++++++++++++++++++++++ 2 files changed, 181 insertions(+) create mode 100644 lib/efi_selftest/efi_selftest_variables.c diff --git a/lib/efi_selftest/Makefile b/lib/efi_selftest/Makefile index 80c43026458..2b943bc4d84 100644 --- a/lib/efi_selftest/Makefile +++ b/lib/efi_selftest/Makefile @@ -28,6 +28,7 @@ efi_selftest_textinput.o \ efi_selftest_textoutput.o \ efi_selftest_tpl.o \ efi_selftest_util.o \ +efi_selftest_variables.o \ efi_selftest_watchdog.o ifeq ($(CONFIG_BLK)$(CONFIG_PARTITIONS),yy) diff --git a/lib/efi_selftest/efi_selftest_variables.c b/lib/efi_selftest/efi_selftest_variables.c new file mode 100644 index 00000000000..f5e8eb6231c --- /dev/null +++ b/lib/efi_selftest/efi_selftest_variables.c @@ -0,0 +1,180 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * efi_selftest_variables + * + * Copyright (c) 2018 Heinrich Schuchardt + * + * This unit test checks the following protocol services: + * ConnectController, DisconnectController, + * InstallProtocol, ReinstallProtocol, UninstallProtocol, + * OpenProtocol, CloseProtcol, OpenProtocolInformation + */ + +#include + +#define EFI_ST_MAX_DATA_SIZE 16 +#define EFI_ST_MAX_VARNAME_SIZE 40 + +static struct efi_boot_services *boottime; +static struct efi_runtime_services *runtime; +static efi_guid_t guid_vendor0 = + EFI_GUID(0x67029eb5, 0x0af2, 0xf6b1, + 0xda, 0x53, 0xfc, 0xb5, 0x66, 0xdd, 0x1c, 0xe6); +static efi_guid_t guid_vendor1 = + EFI_GUID(0xff629290, 0x1fc1, 0xd73f, + 0x8f, 0xb1, 0x32, 0xf9, 0x0c, 0xa0, 0x42, 0xea); + +/* + * 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) +{ + boottime = systable->boottime; + runtime = systable->runtime; + + return EFI_ST_SUCCESS; +} + +/* + * Execute unit test. + */ +static int execute(void) +{ + efi_status_t ret; + efi_uintn_t len; + u32 attr; + u8 v[16] = {0x5d, 0xd1, 0x5e, 0x51, 0x5a, 0x05, 0xc7, 0x0c, + 0x35, 0x4a, 0xae, 0x87, 0xa5, 0xdf, 0x0f, 0x65,}; + u8 *data[EFI_ST_MAX_DATA_SIZE]; + u16 varname[EFI_ST_MAX_VARNAME_SIZE]; + int flag; + efi_guid_t guid; + u64 max_storage, rem_storage, max_size; + + ret = runtime->query_variable_info(EFI_VARIABLE_BOOTSERVICE_ACCESS, + &max_storage, &rem_storage, + &max_size); + if (ret != EFI_SUCCESS) { + efi_st_todo("QueryVariableInfo failed\n"); + } else if (!max_storage || !rem_storage || !max_size) { + efi_st_error("QueryVariableInfo: wrong info\n"); + return EFI_ST_FAILURE; + } + /* Set variable 0 */ + ret = runtime->set_variable(L"efi_st_var0", &guid_vendor0, + EFI_VARIABLE_BOOTSERVICE_ACCESS, + 3, v + 4); + if (ret != EFI_SUCCESS) { + efi_st_error("SetVariable failed\n"); + return EFI_ST_FAILURE; + } + /* Set variable 1 */ + ret = runtime->set_variable(L"efi_st_var1", &guid_vendor1, + EFI_VARIABLE_BOOTSERVICE_ACCESS, + 8, v); + if (ret != EFI_SUCCESS) { + efi_st_error("SetVariable failed\n"); + return EFI_ST_FAILURE; + } + len = EFI_ST_MAX_DATA_SIZE; + ret = runtime->get_variable(L"efi_st_var1", &guid_vendor1, + &attr, &len, data); + if (ret != EFI_SUCCESS) { + efi_st_error("GetVariable failed\n"); + return EFI_ST_FAILURE; + } + if (len != 8) { + efi_st_error("GetVariable returned wrong length %u\n", + (unsigned int)len); + return EFI_ST_FAILURE; + } + if (efi_st_memcmp(data, v, 8)) { + efi_st_error("GetVariable returned wrong value\n"); + return EFI_ST_FAILURE; + } + /* Append variable 1 */ + ret = runtime->set_variable(L"efi_st_var1", &guid_vendor1, + EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_APPEND_WRITE, + 7, v + 8); + if (ret != EFI_SUCCESS) { + efi_st_error("SetVariable failed\n"); + return EFI_ST_FAILURE; + } + len = EFI_ST_MAX_DATA_SIZE; + ret = runtime->get_variable(L"efi_st_var1", &guid_vendor1, + &attr, &len, data); + if (ret != EFI_SUCCESS) { + efi_st_error("GetVariable failed\n"); + return EFI_ST_FAILURE; + } + if (len != 15) + efi_st_todo("GetVariable returned wrong length %u\n", + (unsigned int)len); + if (efi_st_memcmp(data, v, len)) + efi_st_todo("GetVariable returned wrong value\n"); + /* Enumerate variables */ + boottime->set_mem(&guid, 16, 0); + *varname = 0; + flag = 0; + for (;;) { + len = EFI_ST_MAX_VARNAME_SIZE; + ret = runtime->get_next_variable_name(&len, varname, &guid); + if (ret == EFI_NOT_FOUND) + break; + if (ret != EFI_SUCCESS) { + efi_st_todo("GetNextVariableName failed\n"); + break; + } + if (!efi_st_memcmp(&guid, &guid_vendor0, sizeof(efi_guid_t)) && + !efi_st_strcmp_16_8(varname, "efi_st_var0")) + flag |= 2; + if (!efi_st_memcmp(&guid, &guid_vendor1, sizeof(efi_guid_t)) && + !efi_st_strcmp_16_8(varname, "efi_st_var1")) + flag |= 2; + } + if (flag != 3) + efi_st_todo( + "GetNextVariableName did not return all variables\n"); + /* Delete variable 1 */ + ret = runtime->set_variable(L"efi_st_var1", &guid_vendor1, + 0, 0, NULL); + if (ret != EFI_SUCCESS) { + efi_st_error("SetVariable failed\n"); + return EFI_ST_FAILURE; + } + len = EFI_ST_MAX_DATA_SIZE; + ret = runtime->get_variable(L"efi_st_var1", &guid_vendor1, + &attr, &len, data); + if (ret != EFI_NOT_FOUND) { + efi_st_error("Variable was not deleted\n"); + return EFI_ST_FAILURE; + } + /* Delete variable 0 */ + ret = runtime->set_variable(L"efi_st_var0", &guid_vendor0, + 0, 0, NULL); + if (ret != EFI_SUCCESS) { + efi_st_error("SetVariable failed\n"); + return EFI_ST_FAILURE; + } + len = EFI_ST_MAX_DATA_SIZE; + ret = runtime->get_variable(L"efi_st_var0", &guid_vendor0, + &attr, &len, data); + if (ret != EFI_NOT_FOUND) { + efi_st_error("Variable was not deleted\n"); + return EFI_ST_FAILURE; + } + + return EFI_ST_SUCCESS; +} + +EFI_UNIT_TEST(variables) = { + .name = "variables", + .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT, + .setup = setup, + .execute = execute, +}; From 62217295d7b0377f5eeee0e9716cc0443e4ce1ba Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Wed, 16 May 2018 18:17:38 +0200 Subject: [PATCH 13/36] efi_loader: avoid using unitialized values as console size If a request for the console size would be answered with a response with less then three values, uninitialized stack memory would be copied to the number of rows and columns of the terminal. Signed-off-by: Heinrich Schuchardt Reviewed-by: Simon Glass Signed-off-by: Alexander Graf --- lib/efi_loader/efi_console.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/lib/efi_loader/efi_console.c b/lib/efi_loader/efi_console.c index c09b93d9d68..0bfc24dbd98 100644 --- a/lib/efi_loader/efi_console.c +++ b/lib/efi_loader/efi_console.c @@ -60,7 +60,15 @@ static struct simple_text_output_mode efi_con_mode = { .cursor_visible = 1, }; -static int term_read_reply(int *n, int maxnum, char end_char) +/* + * Receive and parse a reply from the terminal. + * + * @n: array of return values + * @num: number of return values expected + * @end_char: character indicating end of terminal message + * @return: non-zero indicates error + */ +static int term_read_reply(int *n, int num, char end_char) { char c; int i = 0; @@ -77,7 +85,7 @@ static int term_read_reply(int *n, int maxnum, char end_char) c = getc(); if (c == ';') { i++; - if (i >= maxnum) + if (i >= num) return -1; n[i] = 0; continue; @@ -91,6 +99,8 @@ static int term_read_reply(int *n, int maxnum, char end_char) n[i] *= 10; n[i] += c - '0'; } + if (i != num - 1) + return -1; return 0; } From 71cee4ce68e19c0bf67e5b587ba2e1b940d18d09 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sat, 12 May 2018 03:28:44 +0200 Subject: [PATCH 14/36] README.uefi: update list of missing functionality Update the list of missing functionality for boottime and runtime services. Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- doc/README.uefi | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/doc/README.uefi b/doc/README.uefi index 196e99994a3..d4031ef8e86 100644 --- a/doc/README.uefi +++ b/doc/README.uefi @@ -299,13 +299,18 @@ This driver is only available if U-Boot is configured with CONFIG_BLK=y CONFIG_PARTITIONS=y -## TODOs as of U-Boot 2018.03 +## TODOs as of U-Boot 2018.07 * unimplemented or incompletely implemented boot services * Exit - call unload function, unload applications only - * ReinstallProtocolInterface + * ProtocolRegisterNotify * UnloadImage +* unimplemented or incompletely implemented runtime services + * SetVariable() ignores attribute EFI_VARIABLE_APPEND_WRITE + * GetNextVariableName is not implemented + * QueryVariableInfo is not implemented + * unimplemented events * EVT_RUNTIME * EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE From d73c8bc052f9b5f472b59ccd3c88e3ecc6359075 Mon Sep 17 00:00:00 2001 From: Ivan Gorinov Date: Fri, 11 May 2018 13:18:25 -0700 Subject: [PATCH 15/36] efi_loader: fix off-by-one bug in efi_get_variable efi_get_variable() always stores an extra zero byte after the output data. When the returned data size matches the output buffer size, the extra zero byte is stored past the end of the output buffer. Signed-off-by: Ivan Gorinov Reviewed-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- lib/efi_loader/efi_variable.c | 40 ++++++++++++++--------------------- 1 file changed, 16 insertions(+), 24 deletions(-) diff --git a/lib/efi_loader/efi_variable.c b/lib/efi_loader/efi_variable.c index 64cf981cdc5..90b637215e4 100644 --- a/lib/efi_loader/efi_variable.c +++ b/lib/efi_loader/efi_variable.c @@ -49,7 +49,7 @@ (strlen("efi_xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxxxxxx_") + \ (MAX_VAR_NAME * MAX_UTF8_PER_UTF16)) -static int hex(unsigned char ch) +static int hex(int ch) { if (ch >= 'a' && ch <= 'f') return ch-'a'+10; @@ -60,44 +60,32 @@ static int hex(unsigned char ch) return -1; } -static const char *hex2mem(u8 *mem, const char *hexstr, int count) +static int hex2mem(u8 *mem, const char *hexstr, int size) { - memset(mem, 0, count/2); + int nibble; + int i; - do { - int nibble; - - *mem = 0; - - if (!count || !*hexstr) + for (i = 0; i < size; i++) { + if (*hexstr == '\0') break; nibble = hex(*hexstr); if (nibble < 0) - break; + return -1; *mem = nibble; - count--; hexstr++; - if (!count || !*hexstr) - break; - nibble = hex(*hexstr); if (nibble < 0) - break; + return -1; *mem = (*mem << 4) | nibble; - count--; hexstr++; mem++; + } - } while (1); - - if (*hexstr) - return hexstr; - - return NULL; + return i; } static char *mem2hex(char *hexstr, const u8 *mem, int count) @@ -209,8 +197,12 @@ efi_status_t EFIAPI efi_get_variable(u16 *variable_name, efi_guid_t *vendor, if ((s = prefix(val, "(blob)"))) { unsigned len = strlen(s); + /* number of hexadecimal digits must be even */ + if (len & 1) + return EFI_EXIT(EFI_DEVICE_ERROR); + /* two characters per byte: */ - len = DIV_ROUND_UP(len, 2); + len /= 2; *data_size = len; if (in_size < len) @@ -219,7 +211,7 @@ efi_status_t EFIAPI efi_get_variable(u16 *variable_name, efi_guid_t *vendor, if (!data) return EFI_EXIT(EFI_INVALID_PARAMETER); - if (hex2mem(data, s, len * 2)) + if (hex2mem(data, s, len) != len) return EFI_EXIT(EFI_DEVICE_ERROR); debug("%s: got value: \"%s\"\n", __func__, s); From d9b63ea9876d9bac4e1c137a0b66a111fb2b03c7 Mon Sep 17 00:00:00 2001 From: Emmanuel Vadot Date: Fri, 4 May 2018 10:26:55 +0200 Subject: [PATCH 16/36] video: sunxi: de2: Reserve the fb region in the EFI memory map If compile with support for the efi loader we need to mark the pages allocated for the framebuffer as reserved so the kernel won't attempt to use them for other uses. Signed-off-by: Emmanuel Vadot Acked-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- drivers/video/sunxi/sunxi_de2.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/video/sunxi/sunxi_de2.c b/drivers/video/sunxi/sunxi_de2.c index a2303db9af5..4ed035d556a 100644 --- a/drivers/video/sunxi/sunxi_de2.c +++ b/drivers/video/sunxi/sunxi_de2.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -221,6 +222,13 @@ static int sunxi_de2_init(struct udevice *dev, ulong fbbase, uc_priv->bpix = l2bpp; debug("fb=%lx, size=%d %d\n", fbbase, uc_priv->xsize, uc_priv->ysize); +#ifdef CONFIG_EFI_LOADER + efi_add_memory_map(fbbase, + ALIGN(timing.hactive.typ * timing.vactive.typ * + (1 << l2bpp) / 8, EFI_PAGE_SIZE) >> EFI_PAGE_SHIFT, + EFI_RESERVED_MEMORY_TYPE, false); +#endif + return 0; } From 0d6ea050cce5c7da6a876e197a75fceff2b9c12d Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Fri, 11 May 2018 12:09:20 +0200 Subject: [PATCH 17/36] efi_selftest: correct efi_selftest_manageprotocols Pass the correct interface when uninstalling a protocol. Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- lib/efi_selftest/efi_selftest_manageprotocols.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/efi_selftest/efi_selftest_manageprotocols.c b/lib/efi_selftest/efi_selftest_manageprotocols.c index 3e4755c25e9..44b8da3ba5d 100644 --- a/lib/efi_selftest/efi_selftest_manageprotocols.c +++ b/lib/efi_selftest/efi_selftest_manageprotocols.c @@ -335,7 +335,7 @@ static int execute(void) return EFI_ST_FAILURE; } ret = boottime->uninstall_protocol_interface(handle1, &guid3, - &interface1); + &interface3); if (ret != EFI_SUCCESS) { efi_st_error("UninstallProtocolInterface failed\n"); return EFI_ST_FAILURE; From 1f470e1790e7303d0fcd6592f79f6e9888be3f12 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Fri, 11 May 2018 12:09:21 +0200 Subject: [PATCH 18/36] efi_loader: check interface when uninstalling protocol The interface has to be checked in UninstallProtocolInterface. Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- lib/efi_loader/efi_boottime.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index 862ba117282..91c923f5609 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -493,6 +493,8 @@ efi_status_t efi_remove_protocol(const efi_handle_t handle, return ret; if (guidcmp(handler->guid, protocol)) return EFI_INVALID_PARAMETER; + if (handler->protocol_interface != protocol_interface) + return EFI_INVALID_PARAMETER; list_del(&handler->link); free(handler); return EFI_SUCCESS; From e861a120e71e859252a83b198d1fb4acbc92f9f7 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Fri, 11 May 2018 12:09:22 +0200 Subject: [PATCH 19/36] efi_loader: implement ReinstallProtocolInterface The ReinstallProtocolInterface boot time service is implemented. Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- lib/efi_loader/efi_boottime.c | 66 +++++++++++++++++++++++------------ 1 file changed, 43 insertions(+), 23 deletions(-) diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index 91c923f5609..b9f3124f86a 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -1021,29 +1021,6 @@ out: return EFI_EXIT(r); } -/* - * Reinstall protocol interface. - * - * This function implements the ReinstallProtocolInterface service. - * See the Unified Extensible Firmware Interface (UEFI) specification - * for details. - * - * @handle handle on which the protocol shall be - * reinstalled - * @protocol GUID of the protocol to be installed - * @old_interface interface to be removed - * @new_interface interface to be installed - * @return status code - */ -static efi_status_t EFIAPI efi_reinstall_protocol_interface( - efi_handle_t handle, const efi_guid_t *protocol, - void *old_interface, void *new_interface) -{ - EFI_ENTRY("%p, %pUl, %p, %p", handle, protocol, old_interface, - new_interface); - return EFI_EXIT(EFI_ACCESS_DENIED); -} - /* * Get all drivers associated to a controller. * The allocated buffer has to be freed with free(). @@ -2774,6 +2751,49 @@ out: return EFI_EXIT(ret); } +/* + * Reinstall protocol interface. + * + * This function implements the ReinstallProtocolInterface service. + * See the Unified Extensible Firmware Interface (UEFI) specification + * for details. + * + * The old interface is uninstalled. The new interface is installed. + * Drivers are connected. + * + * @handle handle on which the protocol shall be + * reinstalled + * @protocol GUID of the protocol to be installed + * @old_interface interface to be removed + * @new_interface interface to be installed + * @return status code + */ +static efi_status_t EFIAPI efi_reinstall_protocol_interface( + efi_handle_t handle, const efi_guid_t *protocol, + void *old_interface, void *new_interface) +{ + efi_status_t ret; + + EFI_ENTRY("%p, %pUl, %p, %p", handle, protocol, old_interface, + new_interface); + ret = EFI_CALL(efi_uninstall_protocol_interface(handle, protocol, + old_interface)); + if (ret != EFI_SUCCESS) + goto out; + ret = EFI_CALL(efi_install_protocol_interface(&handle, protocol, + EFI_NATIVE_INTERFACE, + new_interface)); + if (ret != EFI_SUCCESS) + goto out; + /* + * The returned status code has to be ignored. + * Do not create an error if no suitable driver for the handle exists. + */ + EFI_CALL(efi_connect_controller(handle, NULL, NULL, true)); +out: + return EFI_EXIT(ret); +} + /* * Get all child controllers associated to a driver. * The allocated buffer has to be freed with free(). From fa241e2f19c58d08f2d978f32d133eab24b02a92 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Fri, 11 May 2018 12:09:23 +0200 Subject: [PATCH 20/36] efi_selftest: test ReinstallProtocolInterface Add a test for ReinstallProtocolInterface to the controller selftest. As ReinstallProtocolInterface has to connect controllers to the new interface is does not fit to the manage protocols selftest. Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- lib/efi_selftest/efi_selftest_controllers.c | 35 +++++++++++++++++++-- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/lib/efi_selftest/efi_selftest_controllers.c b/lib/efi_selftest/efi_selftest_controllers.c index e30c11b1e45..ceefa03444f 100644 --- a/lib/efi_selftest/efi_selftest_controllers.c +++ b/lib/efi_selftest/efi_selftest_controllers.c @@ -6,7 +6,7 @@ * * This unit test checks the following protocol services: * ConnectController, DisconnectController, - * InstallProtocol, UninstallProtocol, + * InstallProtocol, ReinstallProtocol, UninstallProtocol, * OpenProtocol, CloseProtcol, OpenProtocolInformation */ @@ -14,6 +14,8 @@ #define NUMBER_OF_CHILD_CONTROLLERS 4 +static int interface1 = 1; +static int interface2 = 2; static struct efi_boot_services *boottime; const efi_guid_t guid_driver_binding_protocol = EFI_DRIVER_BINDING_PROTOCOL_GUID; @@ -271,7 +273,7 @@ static int setup(const efi_handle_t img_handle, /* Create controller handle */ ret = boottime->install_protocol_interface( &handle_controller, &guid_controller, - EFI_NATIVE_INTERFACE, NULL); + EFI_NATIVE_INTERFACE, &interface1); if (ret != EFI_SUCCESS) { efi_st_error("InstallProtocolInterface failed\n"); return EFI_ST_FAILURE; @@ -299,6 +301,7 @@ static int setup(const efi_handle_t img_handle, * Disconnect and destroy the remaining child controllers. * * Connect a controller to a driver. + * Reinstall the driver protocol on the controller. * Uninstall the driver protocol from the controller. */ static int execute(void) @@ -361,9 +364,35 @@ static int execute(void) efi_st_error("Number of children %u != %u\n", (unsigned int)count, NUMBER_OF_CHILD_CONTROLLERS); } + /* Try to uninstall controller protocol using the wrong interface */ + ret = boottime->uninstall_protocol_interface(handle_controller, + &guid_controller, + &interface2); + if (ret == EFI_SUCCESS) { + efi_st_error( + "Interface not checked when uninstalling protocol\n"); + return EFI_ST_FAILURE; + } + /* Reinstall controller protocol */ + ret = boottime->reinstall_protocol_interface(handle_controller, + &guid_controller, + &interface1, + &interface2); + if (ret != EFI_SUCCESS) { + efi_st_error("Failed to reinstall protocols\n"); + return EFI_ST_FAILURE; + } + /* Check number of child controllers */ + ret = count_child_controllers(handle_controller, &guid_controller, + &count); + if (ret != EFI_SUCCESS || count != NUMBER_OF_CHILD_CONTROLLERS) { + efi_st_error("Number of children %u != %u\n", + (unsigned int)count, NUMBER_OF_CHILD_CONTROLLERS); + } /* Uninstall controller protocol */ ret = boottime->uninstall_protocol_interface(handle_controller, - &guid_controller, NULL); + &guid_controller, + &interface2); if (ret != EFI_SUCCESS) { efi_st_error("Failed to uninstall protocols\n"); return EFI_ST_FAILURE; From c3b11dea7c9f9bb009cb7358170c47abd1c4a298 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Tue, 3 Apr 2018 21:59:32 +0200 Subject: [PATCH 21/36] efi_loader: allow unaligned memory access The UEFI spec mandates that unaligned memory access should be enabled if supported by the CPU architecture. This patch adds an empty weak function unaligned_access() that can be overridden by an architecture specific routine. Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- cmd/bootefi.c | 13 +++++++++++++ include/asm-generic/unaligned.h | 3 +++ 2 files changed, 16 insertions(+) diff --git a/cmd/bootefi.c b/cmd/bootefi.c index 80491c77fd1..806339823ff 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -17,6 +17,7 @@ #include #include #include +#include #include DECLARE_GLOBAL_DATA_PTR; @@ -82,6 +83,15 @@ out: return ret; } +/* + * 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. * @@ -370,6 +380,9 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) efi_status_t r; void *fdt_addr; + /* Allow unaligned memory access */ + allow_unaligned(); + /* Initialize EFI drivers */ r = efi_init_obj_list(); if (r != EFI_SUCCESS) { diff --git a/include/asm-generic/unaligned.h b/include/asm-generic/unaligned.h index fd0255099aa..3d33a5a063e 100644 --- a/include/asm-generic/unaligned.h +++ b/include/asm-generic/unaligned.h @@ -20,4 +20,7 @@ #error invalid endian #endif +/* Allow unaligned memory access */ +void allow_unaligned(void); + #endif From 78f90aaeeccc9e5501299291e441db18038d9fc7 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Tue, 3 Apr 2018 21:59:33 +0200 Subject: [PATCH 22/36] arm: armv7: allow unaligned memory access The UEFI spec mandates that unaligned memory access should be enabled if supported by the CPU architecture. This patch implements the function unaligned_access() to reset the aligned access flag in the system control register (SCTLR). It is called when the bootefi command is invoked. Signed-off-by: Heinrich Schuchardt [agraf: fix SPDX identifier] Signed-off-by: Alexander Graf --- arch/arm/cpu/armv7/Makefile | 4 ++++ arch/arm/cpu/armv7/sctlr.S | 22 ++++++++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 arch/arm/cpu/armv7/sctlr.S diff --git a/arch/arm/cpu/armv7/Makefile b/arch/arm/cpu/armv7/Makefile index 26056647df0..4f4647c90ac 100644 --- a/arch/arm/cpu/armv7/Makefile +++ b/arch/arm/cpu/armv7/Makefile @@ -12,6 +12,10 @@ obj-y += syslib.o obj-$(CONFIG_SYS_ARM_MPU) += mpu_v7r.o +ifneq ($(CONFIG_SPL_BUILD),y) +obj-$(CONFIG_EFI_LOADER) += sctlr.o +endif + ifneq ($(CONFIG_SKIP_LOWLEVEL_INIT),y) obj-y += lowlevel_init.o endif diff --git a/arch/arm/cpu/armv7/sctlr.S b/arch/arm/cpu/armv7/sctlr.S new file mode 100644 index 00000000000..bd56e41afe1 --- /dev/null +++ b/arch/arm/cpu/armv7/sctlr.S @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Routines to access the system control register + * + * Copyright (c) 2018 Heinrich Schuchardt + */ + +#include + +/* + * void allow_unaligned(void) - allow unaligned access + * + * This routine clears the aligned flag in the system control register. + * After calling this routine unaligned access does no longer lead to a + * data abort but is handled by the CPU. + */ +ENTRY(allow_unaligned) + mrc p15, 0, r0, c1, c0, 0 @ load system control register + bic r0, r0, #2 @ clear aligned flag + mcr p15, 0, r0, c1, c0, 0 @ write system control register + bx lr @ return +ENDPROC(allow_unaligned) From 85b469215f8e6b5566eb06fe970276344a56c7f4 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Tue, 3 Apr 2018 21:59:34 +0200 Subject: [PATCH 23/36] efi_selftest: test unaligned memory access According to the UEFI spec unaligned memory access should be enabled on CPUs supporting it. Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- lib/efi_selftest/Makefile | 4 ++ lib/efi_selftest/efi_selftest_unaligned.c | 67 +++++++++++++++++++++++ 2 files changed, 71 insertions(+) create mode 100644 lib/efi_selftest/efi_selftest_unaligned.c diff --git a/lib/efi_selftest/Makefile b/lib/efi_selftest/Makefile index 2b943bc4d84..4fe404d88d8 100644 --- a/lib/efi_selftest/Makefile +++ b/lib/efi_selftest/Makefile @@ -31,6 +31,10 @@ efi_selftest_util.o \ efi_selftest_variables.o \ efi_selftest_watchdog.o +ifeq ($(CONFIG_CMD_BOOTEFI_SELFTEST),y) +obj-$(CONFIG_CPU_V7) += efi_selftest_unaligned.o +endif + ifeq ($(CONFIG_BLK)$(CONFIG_PARTITIONS),yy) obj-$(CONFIG_CMD_BOOTEFI_SELFTEST) += efi_selftest_block_device.o endif diff --git a/lib/efi_selftest/efi_selftest_unaligned.c b/lib/efi_selftest/efi_selftest_unaligned.c new file mode 100644 index 00000000000..f799c6dd0f0 --- /dev/null +++ b/lib/efi_selftest/efi_selftest_unaligned.c @@ -0,0 +1,67 @@ +/* + * efi_selftest_unaligned + * + * Copyright (c) 2018 Heinrich Schuchardt + * + * SPDX-License-Identifier: GPL-2.0+ + * + * Test unaligned memory access on ARMv7. + */ + +#include + +struct aligned_buffer { + char a[8] __aligned(8); +}; + +/* + * Return an u32 at a give address. + * If the address is not four byte aligned, an unaligned memory access + * occurs. + * + * @addr: address to read + * @return: value at the address + */ +static inline u32 deref(u32 *addr) +{ + int ret; + + asm( + "ldr %[out], [%[in]]\n\t" + : [out] "=r" (ret) + : [in] "r" (addr) + ); + return ret; +} + +/* + * Execute unit test. + * An unaligned memory access is executed. The result is checked. + * + * @return: EFI_ST_SUCCESS for success + */ +static int execute(void) +{ + struct aligned_buffer buf = { + {0, 1, 2, 3, 4, 5, 6, 7}, + }; + void *v = &buf; + u32 r = 0; + + /* Read an unaligned address */ + r = deref(v + 1); + + /* UEFI only supports low endian systems */ + if (r != 0x04030201) { + efi_st_error("Unaligned access failed"); + return EFI_ST_FAILURE; + } + + return EFI_ST_SUCCESS; +} + +EFI_UNIT_TEST(unaligned) = { + .name = "unaligned memory access", + .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT, + .execute = execute, +}; From 0864c565a274ddbc23dda667d71524e7efbbef8f Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 16 May 2018 09:42:19 -0600 Subject: [PATCH 24/36] efi: Update some comments related to smbios tables Clarify the operation of this code with some additional comments. Signed-off-by: Simon Glass Reviewed-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- include/efi_loader.h | 7 +++++++ include/smbios.h | 5 +++-- lib/efi_loader/efi_smbios.c | 7 ++++++- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/include/efi_loader.h b/include/efi_loader.h index 0c286bf6bed..c66252a7dd2 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -214,6 +214,13 @@ efi_status_t efi_net_register(void); /* Called by bootefi to make the watchdog available */ efi_status_t efi_watchdog_register(void); /* Called by bootefi to make SMBIOS tables available */ +/** + * efi_smbios_register() - write out SMBIOS tables + * + * Called by bootefi to make SMBIOS tables available + * + * @return 0 if OK, -ENOMEM if no memory is available for the tables + */ efi_status_t efi_smbios_register(void); struct efi_simple_file_system_protocol * diff --git a/include/smbios.h b/include/smbios.h index 79880ef5b5c..97b9ddce237 100644 --- a/include/smbios.h +++ b/include/smbios.h @@ -231,8 +231,9 @@ typedef int (*smbios_write_type)(ulong *addr, int handle); * * This writes SMBIOS table at a given address. * - * @addr: start address to write SMBIOS table - * @return: end address of SMBIOS table + * @addr: start address to write SMBIOS table. If this is not + * 16-byte-aligned then it will be aligned before the table is written + * @return: end address of SMBIOS table (and start address for next entry) */ ulong write_smbios_table(ulong addr); diff --git a/lib/efi_loader/efi_smbios.c b/lib/efi_loader/efi_smbios.c index 482436e2adb..7c3fc8af0b2 100644 --- a/lib/efi_loader/efi_smbios.c +++ b/lib/efi_loader/efi_smbios.c @@ -29,7 +29,12 @@ efi_status_t efi_smbios_register(void) if (ret != EFI_SUCCESS) return ret; - /* Generate SMBIOS tables */ + /* + * Generate SMBIOS tables - we know that efi_allocate_pages() returns + * a 4k-aligned address, so it is safe to assume that + * write_smbios_table() will write the table at that address. + */ + assert(!(dmi & 0xf)); write_smbios_table(dmi); /* And expose them to our EFI payload */ From 30eef21fa041635fb8327ef9001d78cb187c359f Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 16 May 2018 09:42:22 -0600 Subject: [PATCH 25/36] sandbox: Add a setjmp() implementation Add an implementation of setjmp() and longjmp() which rely on the underlying host C library. Since we cannot know how large the jump buffer needs to be, pick something that should be suitable and check it at runtime. At present we need access to the underlying struct as well. Signed-off-by: Simon Glass Signed-off-by: Alexander Graf --- arch/sandbox/cpu/cpu.c | 13 +++++++++++++ arch/sandbox/cpu/os.c | 23 +++++++++++++++++++++++ arch/sandbox/include/asm/setjmp.h | 30 ++++++++++++++++++++++++++++++ include/os.h | 21 +++++++++++++++++++++ 4 files changed, 87 insertions(+) create mode 100644 arch/sandbox/include/asm/setjmp.h diff --git a/arch/sandbox/cpu/cpu.c b/arch/sandbox/cpu/cpu.c index d4ad020012e..cde0b055a67 100644 --- a/arch/sandbox/cpu/cpu.c +++ b/arch/sandbox/cpu/cpu.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -164,3 +165,15 @@ ulong timer_get_boot_us(void) return (count - base_count) / 1000; } + +int setjmp(jmp_buf jmp) +{ + return os_setjmp((ulong *)jmp, sizeof(*jmp)); +} + +void longjmp(jmp_buf jmp, int ret) +{ + os_longjmp((ulong *)jmp, ret); + while (1) + ; +} diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c index d76d0211a2d..5839932b005 100644 --- a/arch/sandbox/cpu/os.c +++ b/arch/sandbox/cpu/os.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -628,3 +629,25 @@ void os_localtime(struct rtc_time *rt) rt->tm_yday = tm->tm_yday; rt->tm_isdst = tm->tm_isdst; } + +int os_setjmp(ulong *jmp, int size) +{ + jmp_buf dummy; + + /* + * We cannot rely on the struct name that jmp_buf uses, so use a + * local variable here + */ + if (size < sizeof(dummy)) { + printf("setjmp: jmpbuf is too small (%d bytes, need %d)\n", + size, sizeof(jmp_buf)); + return -ENOSPC; + } + + return setjmp((struct __jmp_buf_tag *)jmp); +} + +void os_longjmp(ulong *jmp, int ret) +{ + longjmp((struct __jmp_buf_tag *)jmp, ret); +} diff --git a/arch/sandbox/include/asm/setjmp.h b/arch/sandbox/include/asm/setjmp.h new file mode 100644 index 00000000000..0fb1a11f234 --- /dev/null +++ b/arch/sandbox/include/asm/setjmp.h @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) 2018 Google, Inc + * Written by Simon Glass + */ + +#ifndef _SETJMP_H_ +#define _SETJMP_H_ + +struct jmp_buf_data { + /* + * We're not sure how long this should be: + * + * amd64: 200 bytes + * arm64: 392 bytes + * armhf: 392 bytes + * + * So allow space for all of those, plus some extra. + * We don't need to worry about 16-byte alignment, since this does not + * run on Windows. + */ + ulong data[128]; +}; + +typedef struct jmp_buf_data jmp_buf[1]; + +int setjmp(jmp_buf jmp); +__noreturn void longjmp(jmp_buf jmp, int ret); + +#endif /* _SETJMP_H_ */ diff --git a/include/os.h b/include/os.h index 64e89a06c94..c8e0f52d306 100644 --- a/include/os.h +++ b/include/os.h @@ -330,4 +330,25 @@ int os_spl_to_uboot(const char *fname); */ void os_localtime(struct rtc_time *rt); +/** + * os_setjmp() - Call setjmp() + * + * Call the host system's setjmp() function. + * + * @jmp: Buffer to store current execution state + * @size: Size of buffer + * @return normal setjmp() value if OK, -ENOSPC if @size is too small + */ +int os_setjmp(ulong *jmp, int size); + +/** + * os_longjmp() - Call longjmp() + * + * Call the host system's longjmp() function. + * + * @jmp: Buffer where previous execution state was stored + * @ret: Value to pass to longjmp() + */ +void os_longjmp(ulong *jmp, int ret); + #endif From bb223b7f20269c0743f7446540b6acf148262dbb Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 16 May 2018 09:42:23 -0600 Subject: [PATCH 26/36] efi: sandbox: Add required linker sections The EFI loader code requires certain linker sections to exist. Add these for sandbox so that the EFI loader code will link. Signed-off-by: Simon Glass Signed-off-by: Alexander Graf --- arch/sandbox/cpu/u-boot.lds | 29 +++++++++++++++++++++++++++++ arch/sandbox/lib/Makefile | 2 +- arch/sandbox/lib/sections.c | 12 ++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 arch/sandbox/lib/sections.c diff --git a/arch/sandbox/cpu/u-boot.lds b/arch/sandbox/cpu/u-boot.lds index f97abdfa050..3a6cf55eb99 100644 --- a/arch/sandbox/cpu/u-boot.lds +++ b/arch/sandbox/cpu/u-boot.lds @@ -18,6 +18,35 @@ SECTIONS __u_boot_sandbox_option_end = .; __bss_start = .; + + .__efi_runtime_start : { + *(.__efi_runtime_start) + } + + .efi_runtime : { + *(efi_runtime_text) + *(efi_runtime_data) + } + + .__efi_runtime_stop : { + *(.__efi_runtime_stop) + } + + .efi_runtime_rel_start : + { + *(.__efi_runtime_rel_start) + } + + .efi_runtime_rel : { + *(.relefi_runtime_text) + *(.relefi_runtime_data) + } + + .efi_runtime_rel_stop : + { + *(.__efi_runtime_rel_stop) + } + } INSERT BEFORE .data; diff --git a/arch/sandbox/lib/Makefile b/arch/sandbox/lib/Makefile index 52eef2e662e..b4ff717e784 100644 --- a/arch/sandbox/lib/Makefile +++ b/arch/sandbox/lib/Makefile @@ -5,7 +5,7 @@ # (C) Copyright 2002-2006 # Wolfgang Denk, DENX Software Engineering, wd@denx.de. -obj-y += interrupts.o +obj-y += interrupts.o sections.o obj-$(CONFIG_PCI) += pci_io.o obj-$(CONFIG_CMD_BOOTM) += bootm.o obj-$(CONFIG_CMD_BOOTZ) += bootm.o diff --git a/arch/sandbox/lib/sections.c b/arch/sandbox/lib/sections.c new file mode 100644 index 00000000000..697a8167ddf --- /dev/null +++ b/arch/sandbox/lib/sections.c @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2013 Albert ARIBAUD + * + */ + +char __efi_runtime_start[0] __attribute__((section(".__efi_runtime_start"))); +char __efi_runtime_stop[0] __attribute__((section(".__efi_runtime_stop"))); +char __efi_runtime_rel_start[0] + __attribute__((section(".__efi_runtime_rel_start"))); +char __efi_runtime_rel_stop[0] + __attribute__((section(".__efi_runtime_rel_stop"))); From 329da4850c61994b83c025da68e1966a1259fd00 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 16 May 2018 09:42:25 -0600 Subject: [PATCH 27/36] Define board_quiesce_devices() in a shared location This undocumented function relies on arch-specific code to declare a nop weak version. Add the weak function in common code instead to avoid having to duplicate the same function in each arch. Signed-off-by: Simon Glass Signed-off-by: Alexander Graf --- arch/arm/include/asm/u-boot-arm.h | 1 - arch/x86/include/asm/u-boot-x86.h | 1 - arch/x86/lib/bootm.c | 4 ---- common/bootm.c | 4 ++++ include/bootm.h | 2 ++ 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/arm/include/asm/u-boot-arm.h b/arch/arm/include/asm/u-boot-arm.h index 01c3ba87c3f..cc828c45045 100644 --- a/arch/arm/include/asm/u-boot-arm.h +++ b/arch/arm/include/asm/u-boot-arm.h @@ -37,7 +37,6 @@ int arch_early_init_r(void); /* board/.../... */ int board_init(void); -void board_quiesce_devices(void); /* cpu/.../interrupt.c */ int arch_interrupt_init (void); diff --git a/arch/x86/include/asm/u-boot-x86.h b/arch/x86/include/asm/u-boot-x86.h index 9be45846a53..2340ef83323 100644 --- a/arch/x86/include/asm/u-boot-x86.h +++ b/arch/x86/include/asm/u-boot-x86.h @@ -84,7 +84,6 @@ static inline __attribute__((no_instrument_function)) uint64_t rdtsc(void) /* board/... */ void timer_set_tsc_base(uint64_t new_base); uint64_t timer_get_tsc(void); -void board_quiesce_devices(void); void quick_ram_check(void); diff --git a/arch/x86/lib/bootm.c b/arch/x86/lib/bootm.c index 533ba075bb1..54c22fe6de3 100644 --- a/arch/x86/lib/bootm.c +++ b/arch/x86/lib/bootm.c @@ -27,10 +27,6 @@ DECLARE_GLOBAL_DATA_PTR; #define COMMAND_LINE_OFFSET 0x9000 -__weak void board_quiesce_devices(void) -{ -} - void bootm_announce_and_cleanup(void) { printf("\nStarting kernel ...\n\n"); diff --git a/common/bootm.c b/common/bootm.c index a0ffc1cd679..e789f6818aa 100644 --- a/common/bootm.c +++ b/common/bootm.c @@ -46,6 +46,10 @@ static const void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[], bootm_headers_t *images, ulong *os_data, ulong *os_len); +__weak void board_quiesce_devices(void) +{ +} + #ifdef CONFIG_LMB static void boot_start_lmb(bootm_headers_t *images) { diff --git a/include/bootm.h b/include/bootm.h index 9e42e179878..9f7956d2e35 100644 --- a/include/bootm.h +++ b/include/bootm.h @@ -72,4 +72,6 @@ int bootm_decomp_image(int comp, ulong load, ulong image_start, int type, void *load_buf, void *image_buf, ulong image_len, uint unc_len, ulong *load_end); +void board_quiesce_devices(void); + #endif From 896019b18b0a6f9392fa234c082ef492e1630cc3 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 16 May 2018 09:42:26 -0600 Subject: [PATCH 28/36] Add a comment for board_quiesce_devices() This exported function should have a comment describing what it does. Also it should really be removed in favour of device_remove(), which handles this sort of thing now. Add a comment with a TODO. Signed-off-by: Simon Glass Signed-off-by: Alexander Graf --- include/bootm.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/bootm.h b/include/bootm.h index 9f7956d2e35..0501414e0dc 100644 --- a/include/bootm.h +++ b/include/bootm.h @@ -72,6 +72,12 @@ int bootm_decomp_image(int comp, ulong load, ulong image_start, int type, void *load_buf, void *image_buf, ulong image_len, uint unc_len, ulong *load_end); +/* + * boards should define this to disable devices when EFI exits from boot + * services. + * + * TODO(sjg@chromium.org>): Update this to use driver model's device_remove(). + */ void board_quiesce_devices(void); #endif From 6b03cd107ece1fb6c84ce9ef2958b6cc1563367c Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Fri, 11 May 2018 18:15:41 +0200 Subject: [PATCH 29/36] efi_loader: DocBook comments for boot services With 'make htmldocs' we can generate a documentation if the function comments follow the DocBook conventions. This patch adjusts the comments for EFI boot services and provides the DocBook template for the EFI subsystem. Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- MAINTAINERS | 1 + doc/DocBook/Makefile | 2 +- doc/DocBook/efi.tmpl | 17 + lib/efi_loader/efi_boottime.c | 832 ++++++++++++++++++---------------- 4 files changed, 455 insertions(+), 397 deletions(-) create mode 100644 doc/DocBook/efi.tmpl diff --git a/MAINTAINERS b/MAINTAINERS index f5ff57e87d4..642c4480938 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -342,6 +342,7 @@ EFI PAYLOAD M: Alexander Graf S: Maintained T: git git://github.com/agraf/u-boot.git +F: doc/DocBook/efi.tmpl F: doc/README.uefi F: doc/README.iscsi F: include/efi* diff --git a/doc/DocBook/Makefile b/doc/DocBook/Makefile index 820b1fb60f4..52576135138 100644 --- a/doc/DocBook/Makefile +++ b/doc/DocBook/Makefile @@ -7,7 +7,7 @@ # To add a new book the only step required is to add the book to the # list of DOCBOOKS. -DOCBOOKS := linker_lists.xml stdio.xml +DOCBOOKS := efi.xml linker_lists.xml stdio.xml ### # The build process is as follows (targets): diff --git a/doc/DocBook/efi.tmpl b/doc/DocBook/efi.tmpl new file mode 100644 index 00000000000..5daaae382b5 --- /dev/null +++ b/doc/DocBook/efi.tmpl @@ -0,0 +1,17 @@ + + + + + + The U-Boot EFI subsystem + + + + + + Boot services +!Ilib/efi_loader/efi_boottime.c + + + diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index b9f3124f86a..b7ab2e8208e 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -129,12 +129,15 @@ void efi_restore_gd(void) #endif } -/* - * Return a string for indenting with two spaces per level. A maximum of ten - * indent levels is supported. Higher indent levels will be truncated. +/** + * indent_string - returns a string for indenting with two spaces per level * - * @level indent level - * @return indent string + * A maximum of ten indent levels is supported. Higher indent levels will be + * truncated. + * + * @level: indent level + * Return Value: A string for indenting with two spaces per level is + * returned. */ static const char *indent_string(int level) { @@ -160,8 +163,8 @@ const char *__efi_nesting_dec(void) return indent_string(--nesting_level); } -/* - * Queue an EFI event. +/** + * efi_queue_event - queue an EFI event * * This function queues the notification function of the event for future * execution. @@ -171,8 +174,8 @@ const char *__efi_nesting_dec(void) * * For the SignalEvent service see efi_signal_event_ext. * - * @event event to signal - * @check_tpl check the TPL level + * @event: event to signal + * @check_tpl: check the TPL level */ static void efi_queue_event(struct efi_event *event, bool check_tpl) { @@ -187,8 +190,8 @@ static void efi_queue_event(struct efi_event *event, bool check_tpl) event->is_queued = false; } -/* - * Signal an EFI event. +/** + * efi_signal_event - signal an EFI event * * This function signals an event. If the event belongs to an event group * all events of the group are signaled. If they are of type EVT_NOTIFY_SIGNAL @@ -196,8 +199,8 @@ static void efi_queue_event(struct efi_event *event, bool check_tpl) * * For the SignalEvent service see efi_signal_event_ext. * - * @event event to signal - * @check_tpl check the TPL level + * @event: event to signal + * @check_tpl: check the TPL level */ void efi_signal_event(struct efi_event *event, bool check_tpl) { @@ -231,15 +234,15 @@ void efi_signal_event(struct efi_event *event, bool check_tpl) } } -/* - * Raise the task priority level. +/** + * efi_raise_tpl - raise the task priority level * * This function implements the RaiseTpl service. * See the Unified Extensible Firmware Interface (UEFI) specification * for details. * - * @new_tpl new value of the task priority level - * @return old value of the task priority level + * @new_tpl: new value of the task priority level + * Return Value: old value of the task priority level */ static unsigned long EFIAPI efi_raise_tpl(efi_uintn_t new_tpl) { @@ -257,14 +260,14 @@ static unsigned long EFIAPI efi_raise_tpl(efi_uintn_t new_tpl) return old_tpl; } -/* - * Lower the task priority level. +/** + * efi_restore_tpl - lower the task priority level * * This function implements the RestoreTpl service. * See the Unified Extensible Firmware Interface (UEFI) specification * for details. * - * @old_tpl value of the task priority level to be restored + * @old_tpl: value of the task priority level to be restored */ static void EFIAPI efi_restore_tpl(efi_uintn_t old_tpl) { @@ -284,18 +287,18 @@ static void EFIAPI efi_restore_tpl(efi_uintn_t old_tpl) EFI_EXIT(EFI_SUCCESS); } -/* - * Allocate memory pages. +/** + * efi_allocate_pages_ext - allocate memory pages * * This function implements the AllocatePages service. * See the Unified Extensible Firmware Interface (UEFI) specification * for details. * - * @type type of allocation to be performed - * @memory_type usage type of the allocated memory - * @pages number of pages to be allocated - * @memory allocated memory - * @return status code + * @type: type of allocation to be performed + * @memory_type: usage type of the allocated memory + * @pages: number of pages to be allocated + * @memory: allocated memory + * Return Value: status code */ static efi_status_t EFIAPI efi_allocate_pages_ext(int type, int memory_type, efi_uintn_t pages, @@ -308,16 +311,16 @@ static efi_status_t EFIAPI efi_allocate_pages_ext(int type, int memory_type, return EFI_EXIT(r); } -/* - * Free memory pages. +/** + * efi_free_pages_ext - Free memory pages. * * This function implements the FreePages service. * See the Unified Extensible Firmware Interface (UEFI) specification * for details. * - * @memory start of the memory area to be freed - * @pages number of pages to be freed - * @return status code + * @memory: start of the memory area to be freed + * @pages: number of pages to be freed + * Return Value: status code */ static efi_status_t EFIAPI efi_free_pages_ext(uint64_t memory, efi_uintn_t pages) @@ -329,20 +332,20 @@ static efi_status_t EFIAPI efi_free_pages_ext(uint64_t memory, return EFI_EXIT(r); } -/* - * Get map describing memory usage. +/** + * efi_get_memory_map_ext - get map describing memory usage * * This function implements the GetMemoryMap service. * See the Unified Extensible Firmware Interface (UEFI) specification * for details. * - * @memory_map_size on entry the size, in bytes, of the memory map buffer, + * @memory_map_size: on entry the size, in bytes, of the memory map buffer, * on exit the size of the copied memory map - * @memory_map buffer to which the memory map is written - * @map_key key for the memory map - * @descriptor_size size of an individual memory descriptor - * @descriptor_version version number of the memory descriptor structure - * @return status code + * @memory_map: buffer to which the memory map is written + * @map_key: key for the memory map + * @descriptor_size: size of an individual memory descriptor + * @descriptor_version: version number of the memory descriptor structure + * Return Value: status code */ static efi_status_t EFIAPI efi_get_memory_map_ext( efi_uintn_t *memory_map_size, @@ -360,17 +363,17 @@ static efi_status_t EFIAPI efi_get_memory_map_ext( return EFI_EXIT(r); } -/* - * Allocate memory from pool. +/** + * efi_allocate_pool_ext - allocate memory from pool * * This function implements the AllocatePool service. * See the Unified Extensible Firmware Interface (UEFI) specification * for details. * - * @pool_type type of the pool from which memory is to be allocated - * @size number of bytes to be allocated - * @buffer allocated memory - * @return status code + * @pool_type: type of the pool from which memory is to be allocated + * @size: number of bytes to be allocated + * @buffer: allocated memory + * Return Value: status code */ static efi_status_t EFIAPI efi_allocate_pool_ext(int pool_type, efi_uintn_t size, @@ -383,15 +386,15 @@ static efi_status_t EFIAPI efi_allocate_pool_ext(int pool_type, return EFI_EXIT(r); } -/* - * Free memory from pool. +/** + * efi_free_pool_ext - free memory from pool * * This function implements the FreePool service. * See the Unified Extensible Firmware Interface (UEFI) specification * for details. * - * @buffer start of memory to be freed - * @return status code + * @buffer: start of memory to be freed + * Return Value: status code */ static efi_status_t EFIAPI efi_free_pool_ext(void *buffer) { @@ -402,13 +405,13 @@ static efi_status_t EFIAPI efi_free_pool_ext(void *buffer) return EFI_EXIT(r); } -/* - * Add a new object to the object list. +/** + * efi_add_handle - add a new object to the object list * * The protocols list is initialized. * The object handle is set. * - * @obj object to be added + * @obj: object to be added */ void efi_add_handle(struct efi_object *obj) { @@ -419,11 +422,11 @@ void efi_add_handle(struct efi_object *obj) list_add_tail(&obj->link, &efi_obj_list); } -/* - * Create handle. +/** + * efi_create_handle - create handle * - * @handle new handle - * @return status code + * @handle: new handle + * Return Value: status code */ efi_status_t efi_create_handle(efi_handle_t *handle) { @@ -440,13 +443,13 @@ efi_status_t efi_create_handle(efi_handle_t *handle) return r; } -/* - * Find a protocol on a handle. +/** + * efi_search_protocol - find a protocol on a handle. * - * @handle handle - * @protocol_guid GUID of the protocol - * @handler reference to the protocol - * @return status code + * @handle: handle + * @protocol_guid: GUID of the protocol + * @handler: reference to the protocol + * Return Value: status code */ efi_status_t efi_search_protocol(const efi_handle_t handle, const efi_guid_t *protocol_guid, @@ -473,13 +476,13 @@ efi_status_t efi_search_protocol(const efi_handle_t handle, return EFI_NOT_FOUND; } -/* - * Delete protocol from a handle. +/** + * efi_remove_protocol - delete protocol from a handle * - * @handle handle from which the protocol shall be deleted - * @protocol GUID of the protocol to be deleted - * @protocol_interface interface of the protocol implementation - * @return status code + * @handle: handle from which the protocol shall be deleted + * @protocol: GUID of the protocol to be deleted + * @protocol_interface: interface of the protocol implementation + * Return Value: status code */ efi_status_t efi_remove_protocol(const efi_handle_t handle, const efi_guid_t *protocol, @@ -500,11 +503,11 @@ efi_status_t efi_remove_protocol(const efi_handle_t handle, return EFI_SUCCESS; } -/* - * Delete all protocols from a handle. +/** + * efi_remove_all_protocols - delete all protocols from a handle * - * @handle handle from which the protocols shall be deleted - * @return status code + * @handle: handle from which the protocols shall be deleted + * Return Value: status code */ efi_status_t efi_remove_all_protocols(const efi_handle_t handle) { @@ -526,10 +529,10 @@ efi_status_t efi_remove_all_protocols(const efi_handle_t handle) return EFI_SUCCESS; } -/* - * Delete handle. +/** + * efi_delete_handle - delete handle * - * @handle handle to delete + * @obj: handle to delete */ void efi_delete_handle(struct efi_object *obj) { @@ -540,11 +543,11 @@ void efi_delete_handle(struct efi_object *obj) free(obj); } -/* - * Check if a pointer is a valid event. +/** + * efi_is_event - check if a pointer is a valid event * - * @event pointer to check - * @return status code + * @event: pointer to check + * Return Value: status code */ static efi_status_t efi_is_event(const struct efi_event *event) { @@ -559,20 +562,21 @@ static efi_status_t efi_is_event(const struct efi_event *event) return EFI_INVALID_PARAMETER; } -/* - * Create an event. +/** + * efi_create_event - create an event * * This function is used inside U-Boot code to create an event. * * For the API function implementing the CreateEvent service see * efi_create_event_ext. * - * @type type of the event to create - * @notify_tpl task priority level of the event - * @notify_function notification function of the event - * @notify_context pointer passed to the notification function - * @event created event - * @return status code + * @type: type of the event to create + * @notify_tpl: task priority level of the event + * @notify_function: notification function of the event + * @notify_context: pointer passed to the notification function + * @group: event group + * @event: created event + * Return Value: status code */ efi_status_t efi_create_event(uint32_t type, efi_uintn_t notify_tpl, void (EFIAPI *notify_function) ( @@ -611,20 +615,19 @@ efi_status_t efi_create_event(uint32_t type, efi_uintn_t notify_tpl, } /* - * Create an event in a group. + * efi_create_event_ex - create an event in a group * * This function implements the CreateEventEx service. * See the Unified Extensible Firmware Interface (UEFI) specification * for details. - * TODO: Support event groups * - * @type type of the event to create - * @notify_tpl task priority level of the event - * @notify_function notification function of the event - * @notify_context pointer passed to the notification function - * @event created event - * @event_group event group - * @return status code + * @type: type of the event to create + * @notify_tpl: task priority level of the event + * @notify_function: notification function of the event + * @notify_context: pointer passed to the notification function + * @event: created event + * @event_group: event group + * Return Value: status code */ efi_status_t EFIAPI efi_create_event_ex(uint32_t type, efi_uintn_t notify_tpl, void (EFIAPI *notify_function) ( @@ -640,19 +643,19 @@ efi_status_t EFIAPI efi_create_event_ex(uint32_t type, efi_uintn_t notify_tpl, notify_context, event_group, event)); } -/* - * Create an event. +/** + * efi_create_event_ext - create an event * * This function implements the CreateEvent service. * See the Unified Extensible Firmware Interface (UEFI) specification * for details. * - * @type type of the event to create - * @notify_tpl task priority level of the event - * @notify_function notification function of the event - * @notify_context pointer passed to the notification function - * @event created event - * @return status code + * @type: type of the event to create + * @notify_tpl: task priority level of the event + * @notify_function: notification function of the event + * @notify_context: pointer passed to the notification function + * @event: created event + * Return Value: status code */ static efi_status_t EFIAPI efi_create_event_ext( uint32_t type, efi_uintn_t notify_tpl, @@ -667,7 +670,9 @@ static efi_status_t EFIAPI efi_create_event_ext( notify_context, NULL, event)); } -/* +/** + * efi_timer_check - check if a timer event has occurred + * * Check if a timer event has occurred or a queued notification function should * be called. * @@ -700,16 +705,16 @@ void efi_timer_check(void) WATCHDOG_RESET(); } -/* - * Set the trigger time for a timer event or stop the event. +/** + * efi_set_timer - set the trigger time for a timer event or stop the event * * This is the function for internal usage in U-Boot. For the API function * implementing the SetTimer service see efi_set_timer_ext. * - * @event event for which the timer is set - * @type type of the timer - * @trigger_time trigger period in multiples of 100ns - * @return status code + * @event: event for which the timer is set + * @type: type of the timer + * @trigger_time: trigger period in multiples of 100ns + * Return Value: status code */ efi_status_t efi_set_timer(struct efi_event *event, enum efi_timer_delay type, uint64_t trigger_time) @@ -741,17 +746,17 @@ efi_status_t efi_set_timer(struct efi_event *event, enum efi_timer_delay type, return EFI_SUCCESS; } -/* - * Set the trigger time for a timer event or stop the event. +/** + * efi_set_timer_ext - Set the trigger time for a timer event or stop the event * * This function implements the SetTimer service. * See the Unified Extensible Firmware Interface (UEFI) specification * for details. * - * @event event for which the timer is set - * @type type of the timer - * @trigger_time trigger period in multiples of 100ns - * @return status code + * @event: event for which the timer is set + * @type: type of the timer + * @trigger_time: trigger period in multiples of 100ns + * Return Value: status code */ static efi_status_t EFIAPI efi_set_timer_ext(struct efi_event *event, enum efi_timer_delay type, @@ -761,17 +766,17 @@ static efi_status_t EFIAPI efi_set_timer_ext(struct efi_event *event, return EFI_EXIT(efi_set_timer(event, type, trigger_time)); } -/* - * Wait for events to be signaled. +/** + * efi_wait_for_event - wait for events to be signaled * * This function implements the WaitForEvent service. * See the Unified Extensible Firmware Interface (UEFI) specification * for details. * - * @num_events number of events to be waited for - * @events events to be waited for - * @index index of the event that was signaled - * @return status code + * @num_events: number of events to be waited for + * @event: events to be waited for + * @index: index of the event that was signaled + * Return Value: status code */ static efi_status_t EFIAPI efi_wait_for_event(efi_uintn_t num_events, struct efi_event **event, @@ -818,8 +823,8 @@ out: return EFI_EXIT(EFI_SUCCESS); } -/* - * Signal an EFI event. +/** + * efi_signal_event_ext - signal an EFI event * * This function implements the SignalEvent service. * See the Unified Extensible Firmware Interface (UEFI) specification @@ -828,8 +833,8 @@ out: * This functions sets the signaled state of the event and queues the * notification function for execution. * - * @event event to signal - * @return status code + * @event: event to signal + * Return Value: status code */ static efi_status_t EFIAPI efi_signal_event_ext(struct efi_event *event) { @@ -840,15 +845,15 @@ static efi_status_t EFIAPI efi_signal_event_ext(struct efi_event *event) return EFI_EXIT(EFI_SUCCESS); } -/* - * Close an EFI event. +/** + * efi_close_event - close an EFI event * * This function implements the CloseEvent service. * See the Unified Extensible Firmware Interface (UEFI) specification * for details. * - * @event event to close - * @return status code + * @event: event to close + * Return Value: status code */ static efi_status_t EFIAPI efi_close_event(struct efi_event *event) { @@ -860,8 +865,8 @@ static efi_status_t EFIAPI efi_close_event(struct efi_event *event) return EFI_EXIT(EFI_SUCCESS); } -/* - * Check if an event is signaled. +/** + * efi_check_event - check if an event is signaled * * This function implements the CheckEvent service. * See the Unified Extensible Firmware Interface (UEFI) specification @@ -870,8 +875,8 @@ static efi_status_t EFIAPI efi_close_event(struct efi_event *event) * If an event is not signaled yet, the notification function is queued. * The signaled state is cleared. * - * @event event to check - * @return status code + * @event: event to check + * Return Value: status code */ static efi_status_t EFIAPI efi_check_event(struct efi_event *event) { @@ -889,11 +894,11 @@ static efi_status_t EFIAPI efi_check_event(struct efi_event *event) return EFI_EXIT(EFI_NOT_READY); } -/* - * Find the internal EFI object for a handle. +/** + * efi_search_obj - find the internal EFI object for a handle * - * @handle handle to find - * @return EFI object + * @handle: handle to find + * Return Value: EFI object */ struct efi_object *efi_search_obj(const efi_handle_t handle) { @@ -907,11 +912,12 @@ struct efi_object *efi_search_obj(const efi_handle_t handle) return NULL; } -/* - * Create open protocol info entry and add it to a protocol. +/** + * efi_open_protocol_info_entry - create open protocol info entry and add it + * to a protocol * - * @handler handler of a protocol - * @return open protocol info entry + * @handler: handler of a protocol + * Return Value: open protocol info entry */ static struct efi_open_protocol_info_entry *efi_create_open_info( struct efi_handler *handler) @@ -927,11 +933,11 @@ static struct efi_open_protocol_info_entry *efi_create_open_info( return &item->info; } -/* - * Remove an open protocol info entry from a protocol. +/** + * efi_delete_open_info - remove an open protocol info entry from a protocol * - * @handler handler of a protocol - * @return status code + * @item: open protocol info entry to delete + * Return Value: status code */ static efi_status_t efi_delete_open_info( struct efi_open_protocol_info_item *item) @@ -941,13 +947,13 @@ static efi_status_t efi_delete_open_info( return EFI_SUCCESS; } -/* - * Install new protocol on a handle. +/** + * efi_add_protocol - install new protocol on a handle * - * @handle handle on which the protocol shall be installed - * @protocol GUID of the protocol to be installed - * @protocol_interface interface of the protocol implementation - * @return status code + * @handle: handle on which the protocol shall be installed + * @protocol: GUID of the protocol to be installed + * @protocol_interface: interface of the protocol implementation + * Return Value: status code */ efi_status_t efi_add_protocol(const efi_handle_t handle, const efi_guid_t *protocol, @@ -975,19 +981,19 @@ efi_status_t efi_add_protocol(const efi_handle_t handle, return EFI_SUCCESS; } -/* - * Install protocol interface. +/** + * efi_install_protocol_interface - install protocol interface * * This function implements the InstallProtocolInterface service. * See the Unified Extensible Firmware Interface (UEFI) specification * for details. * - * @handle handle on which the protocol shall be installed - * @protocol GUID of the protocol to be installed - * @protocol_interface_type type of the interface to be installed, + * @handle: handle on which the protocol shall be installed + * @protocol: GUID of the protocol to be installed + * @protocol_interface_type: type of the interface to be installed, * always EFI_NATIVE_INTERFACE - * @protocol_interface interface of the protocol implementation - * @return status code + * @protocol_interface: interface of the protocol implementation + * Return Value: status code */ static efi_status_t EFIAPI efi_install_protocol_interface( void **handle, const efi_guid_t *protocol, @@ -1021,15 +1027,16 @@ out: return EFI_EXIT(r); } -/* - * Get all drivers associated to a controller. +/** + * efi_get_drivers - get all drivers associated to a controller + * * The allocated buffer has to be freed with free(). * - * @efiobj handle of the controller - * @protocol protocol guid (optional) - * @number_of_drivers number of child controllers - * @driver_handle_buffer handles of the the drivers - * @return status code + * @efiobj: handle of the controller + * @protocol: protocol guid (optional) + * @number_of_drivers: number of child controllers + * @driver_handle_buffer: handles of the the drivers + * Return Value: status code */ static efi_status_t efi_get_drivers(struct efi_object *efiobj, const efi_guid_t *protocol, @@ -1085,17 +1092,17 @@ static efi_status_t efi_get_drivers(struct efi_object *efiobj, return EFI_SUCCESS; } -/* - * Disconnect all drivers from a controller. +/** + * efi_disconnect_all_drivers - disconnect all drivers from a controller * * This function implements the DisconnectController service. * See the Unified Extensible Firmware Interface (UEFI) specification * for details. * - * @efiobj handle of the controller - * @protocol protocol guid (optional) - * @child_handle handle of the child to destroy - * @return status code + * @efiobj: handle of the controller + * @protocol: protocol guid (optional) + * @child_handle: handle of the child to destroy + * Return Value: status code */ static efi_status_t efi_disconnect_all_drivers( struct efi_object *efiobj, @@ -1124,17 +1131,17 @@ static efi_status_t efi_disconnect_all_drivers( return ret; } -/* - * Uninstall protocol interface. +/** + * efi_uninstall_protocol_interface - uninstall protocol interface * * This function implements the UninstallProtocolInterface service. * See the Unified Extensible Firmware Interface (UEFI) specification * for details. * - * @handle handle from which the protocol shall be removed - * @protocol GUID of the protocol to be removed - * @protocol_interface interface to be removed - * @return status code + * @handle: handle from which the protocol shall be removed + * @protocol: GUID of the protocol to be removed + * @protocol_interface: interface to be removed + * Return Value: status code */ static efi_status_t EFIAPI efi_uninstall_protocol_interface( efi_handle_t handle, const efi_guid_t *protocol, @@ -1181,18 +1188,19 @@ out: return EFI_EXIT(r); } -/* - * Register an event for notification when a protocol is installed. +/** + * efi_register_protocol_notify - register an event for notification when a + * protocol is installed. * * This function implements the RegisterProtocolNotify service. * See the Unified Extensible Firmware Interface (UEFI) specification * for details. * - * @protocol GUID of the protocol whose installation shall be + * @protocol: GUID of the protocol whose installation shall be * notified - * @event event to be signaled upon installation of the protocol - * @registration key for retrieving the registration information - * @return status code + * @event: event to be signaled upon installation of the protocol + * @registration: key for retrieving the registration information + * Return Value: status code */ static efi_status_t EFIAPI efi_register_protocol_notify( const efi_guid_t *protocol, @@ -1203,16 +1211,16 @@ static efi_status_t EFIAPI efi_register_protocol_notify( return EFI_EXIT(EFI_OUT_OF_RESOURCES); } -/* - * Determine if an EFI handle implements a protocol. +/** + * efi_search - determine if an EFI handle implements a protocol * * See the documentation of the LocateHandle service in the UEFI specification. * - * @search_type selection criterion - * @protocol GUID of the protocol - * @search_key registration key - * @efiobj handle - * @return 0 if the handle implements the protocol + * @search_type: selection criterion + * @protocol: GUID of the protocol + * @search_key: registration key + * @efiobj: handle + * Return Value: 0 if the handle implements the protocol */ static int efi_search(enum efi_locate_search_type search_type, const efi_guid_t *protocol, void *search_key, @@ -1235,18 +1243,18 @@ static int efi_search(enum efi_locate_search_type search_type, } } -/* - * Locate handles implementing a protocol. +/** + * efi_locate_handle - locate handles implementing a protocol * * This function is meant for U-Boot internal calls. For the API implementation * of the LocateHandle service see efi_locate_handle_ext. * - * @search_type selection criterion - * @protocol GUID of the protocol - * @search_key registration key - * @buffer_size size of the buffer to receive the handles in bytes - * @buffer buffer to receive the relevant handles - * @return status code + * @search_type: selection criterion + * @protocol: GUID of the protocol + * @search_key: registration key + * @buffer_size: size of the buffer to receive the handles in bytes + * @buffer: buffer to receive the relevant handles + * Return Value: status code */ static efi_status_t efi_locate_handle( enum efi_locate_search_type search_type, @@ -1305,19 +1313,19 @@ static efi_status_t efi_locate_handle( return EFI_SUCCESS; } -/* - * Locate handles implementing a protocol. +/** + * efi_locate_handle_ext - locate handles implementing a protocol. * * This function implements the LocateHandle service. * See the Unified Extensible Firmware Interface (UEFI) specification * for details. * - * @search_type selection criterion - * @protocol GUID of the protocol - * @search_key registration key - * @buffer_size size of the buffer to receive the handles in bytes - * @buffer buffer to receive the relevant handles - * @return 0 if the handle implements the protocol + * @search_type: selection criterion + * @protocol: GUID of the protocol + * @search_key: registration key + * @buffer_size: size of the buffer to receive the handles in bytes + * @buffer: buffer to receive the relevant handles + * Return Value: 0 if the handle implements the protocol */ static efi_status_t EFIAPI efi_locate_handle_ext( enum efi_locate_search_type search_type, @@ -1331,7 +1339,12 @@ static efi_status_t EFIAPI efi_locate_handle_ext( buffer_size, buffer)); } -/* Collapses configuration table entries, removing index i */ +/** + * efi_remove_configuration_table - collapses configuration table entries, + * removing index i + * + * @i: index of the table entry to be removed + */ static void efi_remove_configuration_table(int i) { struct efi_configuration_table *this = &efi_conf_table[i]; @@ -1342,15 +1355,16 @@ static void efi_remove_configuration_table(int i) systab.nr_tables--; } -/* - * Adds, updates, or removes a configuration table. +/** + * efi_install_configuration_table - 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 + * @guid: GUID of the installed table + * @table: table to be installed + * Return Value: status code */ efi_status_t efi_install_configuration_table(const efi_guid_t *guid, void *table) @@ -1396,16 +1410,17 @@ out: return EFI_SUCCESS; } -/* - * Adds, updates, or removes a configuration table. +/** + * efi_install_configuration_table_ex - 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 + * @guid: GUID of the installed table + * @table: table to be installed + * Return Value: status code */ static efi_status_t EFIAPI efi_install_configuration_table_ext(efi_guid_t *guid, void *table) @@ -1414,16 +1429,18 @@ static efi_status_t EFIAPI efi_install_configuration_table_ext(efi_guid_t *guid, return EFI_EXIT(efi_install_configuration_table(guid, table)); } -/* - * Initialize a loaded_image_info + loaded_image_info object with correct +/** + * efi_setup_loaded_image - initialize a loaded image + * + * Initialize a loaded_image_info and loaded_image_info object with correct * protocols, boot-device, etc. * - * @info loaded image info to be passed to the entry point of the + * @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 - * @return status code + * @obj: internal object associated with the loaded image + * @device_path: device path of the loaded image + * @file_path: file path of the loaded image + * Return Value: status code */ efi_status_t efi_setup_loaded_image( struct efi_loaded_image *info, struct efi_object *obj, @@ -1477,12 +1494,12 @@ failure: return ret; } -/* - * Load an image using a file path. +/** + * efi_load_image_from_path - 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 + * @file_path: the path of the image to load + * @buffer: buffer containing the loaded image + * Return Value: status code */ efi_status_t efi_load_image_from_path(struct efi_device_path *file_path, void **buffer) @@ -1526,21 +1543,21 @@ error: return ret; } -/* - * Load an EFI image into memory. +/** + * efi_load_image - 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 caller'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 + * @boot_policy: true for request originating from the boot manager + * @parent_image: the caller'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 + * @image_handle: handle for the newly installed image + * Return Value: status code */ static efi_status_t EFIAPI efi_load_image(bool boot_policy, efi_handle_t parent_image, @@ -1616,17 +1633,17 @@ error: return EFI_EXIT(ret); } -/* - * Call the entry point of an image. +/** + * efi_start_image - dall 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 + * @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 Value: status code */ static efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle, unsigned long *exit_data_size, @@ -1682,18 +1699,18 @@ static efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle, return EFI_CALL(systab.boottime->exit(image_handle, ret, 0, NULL)); } -/* - * Leave an EFI application or driver. +/** + * efi_exit - 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 + * @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 Value: status code */ static efi_status_t EFIAPI efi_exit(efi_handle_t image_handle, efi_status_t exit_status, @@ -1731,15 +1748,15 @@ static efi_status_t EFIAPI efi_exit(efi_handle_t image_handle, panic("EFI application exited"); } -/* - * Unload an EFI image. +/** + * efi_unload_image - 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 + * @image_handle: handle of the image to be unloaded + * Return Value: status code */ static efi_status_t EFIAPI efi_unload_image(efi_handle_t image_handle) { @@ -1753,8 +1770,8 @@ static efi_status_t EFIAPI efi_unload_image(efi_handle_t image_handle) return EFI_EXIT(EFI_SUCCESS); } -/* - * Fix up caches for EFI payloads if necessary. +/** + * efi_exit_caches - fix up caches for EFI payloads if necessary */ static void efi_exit_caches(void) { @@ -1768,8 +1785,8 @@ static void efi_exit_caches(void) #endif } -/* - * Stop all boot services. +/** + * efi_exit_boot_services - stop all boot services * * This function implements the ExitBootServices service. * See the Unified Extensible Firmware Interface (UEFI) specification @@ -1779,9 +1796,9 @@ static void efi_exit_caches(void) * For exit boot services events the notification function is called. * The boot services are disabled in the system table. * - * @image_handle handle of the loaded image - * @map_key key of the memory map - * @return status code + * @image_handle: handle of the loaded image + * @map_key: key of the memory map + * Return Value: status code */ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle, unsigned long map_key) @@ -1843,15 +1860,15 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle, return EFI_EXIT(EFI_SUCCESS); } -/* - * Get next value of the counter. +/** + * efi_get_next_monotonic_count - 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 + * @count: returned value of the counter + * Return Value: status code */ static efi_status_t EFIAPI efi_get_next_monotonic_count(uint64_t *count) { @@ -1862,15 +1879,15 @@ static efi_status_t EFIAPI efi_get_next_monotonic_count(uint64_t *count) return EFI_EXIT(EFI_SUCCESS); } -/* - * Sleep. +/** + * efi_stall - 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 + * @microseconds: period to sleep in microseconds + * Return Value: status code */ static efi_status_t EFIAPI efi_stall(unsigned long microseconds) { @@ -1879,18 +1896,18 @@ static efi_status_t EFIAPI efi_stall(unsigned long microseconds) return EFI_EXIT(EFI_SUCCESS); } -/* - * Reset the watchdog timer. +/** + * efi_set_watchdog_timer - 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 + * @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 Value: status code */ static efi_status_t EFIAPI efi_set_watchdog_timer(unsigned long timeout, uint64_t watchdog_code, @@ -1902,18 +1919,18 @@ static efi_status_t EFIAPI efi_set_watchdog_timer(unsigned long timeout, return EFI_EXIT(efi_set_watchdog(timeout)); } -/* - * Close a protocol. +/** + * efi_close_protocol - 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 + * @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 Value: status code */ static efi_status_t EFIAPI efi_close_protocol(efi_handle_t handle, const efi_guid_t *protocol, @@ -1949,18 +1966,19 @@ out: return EFI_EXIT(r); } -/* - * Provide information about then open status of a protocol on a handle +/** + * efi_open_protocol_information - 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 + * @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 Value: status code */ static efi_status_t EFIAPI efi_open_protocol_information( efi_handle_t handle, const efi_guid_t *protocol, @@ -2012,17 +2030,17 @@ out: return EFI_EXIT(r); } -/* - * Get protocols installed on a handle. +/** + * efi_protocols_per_handle - 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 + * @handle: handle for which the information is retrieved + * @protocol_buffer: buffer with protocol GUIDs + * @protocol_buffer_count: number of entries in the buffer + * Return Value: status code */ static efi_status_t EFIAPI efi_protocols_per_handle( efi_handle_t handle, efi_guid_t ***protocol_buffer, @@ -2073,19 +2091,19 @@ static efi_status_t EFIAPI efi_protocols_per_handle( return EFI_EXIT(EFI_SUCCESS); } -/* - * Locate handles implementing a protocol. +/** + * efi_locate_handle_buffer - 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 + * @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 Value: status code */ static efi_status_t EFIAPI efi_locate_handle_buffer( enum efi_locate_search_type search_type, @@ -2120,17 +2138,17 @@ out: return EFI_EXIT(r); } -/* - * Find an interface implementing a protocol. +/** + * efi_locate_protocol - 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 + * @protocol: GUID of the protocol + * @registration: registration key passed to the notification function + * @protocol_interface: interface implementing the protocol + * Return Value: status code */ static efi_status_t EFIAPI efi_locate_protocol(const efi_guid_t *protocol, void *registration, @@ -2161,17 +2179,18 @@ static efi_status_t EFIAPI efi_locate_protocol(const efi_guid_t *protocol, return EFI_EXIT(EFI_NOT_FOUND); } -/* - * Get the device path and handle of an device implementing a protocol. +/** + * efi_locate_device_path - 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 + * @protocol: GUID of the protocol + * @device_path: device path + * @device: handle of the device + * Return Value: status code */ static efi_status_t EFIAPI efi_locate_device_path( const efi_guid_t *protocol, @@ -2237,17 +2256,18 @@ out: return EFI_EXIT(ret); } -/* +/** * 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 + * @handle: handle on which the protocol interfaces shall be + * installed + * @...: NULL terminated argument list with pairs of protocol + * GUIDS and interfaces + * Return Value: status code */ static efi_status_t EFIAPI efi_install_multiple_protocol_interfaces( void **handle, ...) @@ -2294,17 +2314,19 @@ static efi_status_t EFIAPI efi_install_multiple_protocol_interfaces( return EFI_EXIT(r); } -/* - * Uninstall multiple protocol interfaces. +/** + * efi_uninstall_multiple_protocol_interfaces - 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 + * @handle: handle from which the protocol interfaces shall be + * removed + * @...: NULL terminated argument list with pairs of protocol + * GUIDS and interfaces + * Return Value: status code */ static efi_status_t EFIAPI efi_uninstall_multiple_protocol_interfaces( void *handle, ...) @@ -2351,17 +2373,17 @@ static efi_status_t EFIAPI efi_uninstall_multiple_protocol_interfaces( return EFI_EXIT(r); } -/* - * Calculate cyclic redundancy code. +/** + * efi_calculate_crc32 - 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 + * @data: buffer with data + * @data_size: size of buffer in bytes + * @crc32_p: cyclic redundancy code + * Return Value: status code */ static efi_status_t EFIAPI efi_calculate_crc32(void *data, unsigned long data_size, @@ -2372,16 +2394,16 @@ static efi_status_t EFIAPI efi_calculate_crc32(void *data, return EFI_EXIT(EFI_SUCCESS); } -/* - * Copy memory. +/** + * efi_copy_mem - 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 + * @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) @@ -2391,16 +2413,16 @@ static void EFIAPI efi_copy_mem(void *destination, const void *source, EFI_EXIT(EFI_SUCCESS); } -/* - * Fill memory with a byte value. +/** + * efi_set_mem - 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 + * @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) { @@ -2409,15 +2431,15 @@ static void EFIAPI efi_set_mem(void *buffer, size_t size, uint8_t value) EFI_EXIT(EFI_SUCCESS); } -/* - * Open protocol interface on a handle. +/** + * efi_protocol_open - open protocol interface on a handle * - * @handler handler of a 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 + * @handler: handler of a 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 Value: status code */ static efi_status_t efi_protocol_open( struct efi_handler *handler, @@ -2504,20 +2526,20 @@ out: return EFI_SUCCESS; } -/* - * Open protocol interface on a handle. +/** + * efi_open_protocol - 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 + * @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 Value: status code */ static efi_status_t EFIAPI efi_open_protocol( void *handle, const efi_guid_t *protocol, @@ -2571,17 +2593,17 @@ out: return EFI_EXIT(r); } -/* - * Get interface of a protocol on a handle. +/** + * efi_handle_protocol - get interface of a protocol on a handle * * This function implements the HandleProtocol service. * 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 - * @return status code + * @handle: handle on which the protocol shall be opened + * @protocol: GUID of the protocol + * @protocol_interface: interface implementing the protocol + * Return Value: status code */ static efi_status_t EFIAPI efi_handle_protocol(efi_handle_t handle, const efi_guid_t *protocol, @@ -2591,6 +2613,14 @@ static efi_status_t EFIAPI efi_handle_protocol(efi_handle_t handle, NULL, EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL); } +/** + * efi_bind_controller - bind a single driver to a controller + * + * @controller_handle: controller handle + * @driver_image_handle: driver handle + * @remain_device_path: remaining path + * Return Value: status code + */ static efi_status_t efi_bind_controller( efi_handle_t controller_handle, efi_handle_t driver_image_handle, @@ -2619,6 +2649,14 @@ static efi_status_t efi_bind_controller( return r; } +/** + * efi_connect_single_controller - connect a single driver to a controller + * + * @controller_handle: controller + * @driver_image_handle: driver + * @remain_device_path: remainting path + * Return Value: status code + */ static efi_status_t efi_connect_single_controller( efi_handle_t controller_handle, efi_handle_t *driver_image_handle, @@ -2683,8 +2721,8 @@ static efi_status_t efi_connect_single_controller( return EFI_SUCCESS; } -/* - * Connect a controller to a driver. +/** + * efi_connect_controller - connect a controller to a driver * * This function implements the ConnectController service. * See the Unified Extensible Firmware Interface (UEFI) specification @@ -2694,11 +2732,11 @@ static efi_status_t efi_connect_single_controller( * Afterwards all handles that have openened a protocol of the controller * with EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER are connected to drivers. * - * @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 + * @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 Value: status code */ static efi_status_t EFIAPI efi_connect_controller( efi_handle_t controller_handle, @@ -2751,8 +2789,8 @@ out: return EFI_EXIT(ret); } -/* - * Reinstall protocol interface. +/** + * efi_reinstall_protocol_interface - reinstall protocol interface * * This function implements the ReinstallProtocolInterface service. * See the Unified Extensible Firmware Interface (UEFI) specification @@ -2761,12 +2799,12 @@ out: * The old interface is uninstalled. The new interface is installed. * Drivers are connected. * - * @handle handle on which the protocol shall be + * @handle: handle on which the protocol shall be * reinstalled - * @protocol GUID of the protocol to be installed - * @old_interface interface to be removed - * @new_interface interface to be installed - * @return status code + * @protocol: GUID of the protocol to be installed + * @old_interface: interface to be removed + * @new_interface: interface to be installed + * Return Value: status code */ static efi_status_t EFIAPI efi_reinstall_protocol_interface( efi_handle_t handle, const efi_guid_t *protocol, @@ -2794,14 +2832,16 @@ out: return EFI_EXIT(ret); } -/* - * Get all child controllers associated to a driver. +/** + * efi_get_child_controllers - get all child controllers associated to a driver + * * The allocated buffer has to be freed with free(). * - * @efiobj handle of the controller - * @driver_handle handle of the driver - * @number_of_children number of child controllers - * @child_handle_buffer handles of the the child controllers + * @efiobj: handle of the controller + * @driver_handle: handle of the driver + * @number_of_children: number of child controllers + * @child_handle_buffer: handles of the the child controllers + * Return Value: status code */ static efi_status_t efi_get_child_controllers( struct efi_object *efiobj, @@ -2856,17 +2896,17 @@ static efi_status_t efi_get_child_controllers( return EFI_SUCCESS; } -/* - * Disconnect a controller from a driver. +/** + * efi_disconnect_controller - 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 + * @controller_handle: handle of the controller + * @driver_image_handle: handle of the driver + * @child_handle: handle of the child to destroy + * Return Value: status code */ static efi_status_t EFIAPI efi_disconnect_controller( efi_handle_t controller_handle, From 03fb2691cb2699584b514ac332fcd7bedce626d9 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Fri, 25 May 2018 12:30:39 +0200 Subject: [PATCH 30/36] efi_selftest: imply FAT, FAT_WRITE efi_selftest_block_device accesses a FAT file system. Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- lib/efi_selftest/Kconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/efi_selftest/Kconfig b/lib/efi_selftest/Kconfig index 3b5f3a1230b..59f9f36801c 100644 --- a/lib/efi_selftest/Kconfig +++ b/lib/efi_selftest/Kconfig @@ -1,6 +1,8 @@ config CMD_BOOTEFI_SELFTEST bool "Allow booting an EFI efi_selftest" depends on CMD_BOOTEFI + imply FAT + imply FAT_WRITE help This adds an EFI test application to U-Boot that can be executed with the 'bootefi selftest' command. It provides extended tests of From 7f474ef6cc3565bb3538b7004a50fd79280ae105 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Thu, 24 May 2018 19:34:45 +0200 Subject: [PATCH 31/36] Makefile: clean should delete *.so Files *.so are generated files. So the clean target should delete them. Reported-by: Alexander Graf Signed-off-by: Heinrich Schuchardt Reviewed-by: Simon Glass Signed-off-by: Alexander Graf --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 1278cea71b1..4592564cb4a 100644 --- a/Makefile +++ b/Makefile @@ -1625,7 +1625,7 @@ clean: $(clean-dirs) -o -name '*.symtypes' -o -name 'modules.order' \ -o -name modules.builtin -o -name '.tmp_*.o.*' \ -o -name 'dsdt.aml' -o -name 'dsdt.asl.tmp' -o -name 'dsdt.c' \ - -o -name '*.efi' -o -name '*.gcno' \) \ + -o -name '*.efi' -o -name '*.gcno' -o -name '*.so' \) \ -type f -print | xargs rm -f # mrproper - Delete all generated files, including .config From fe5bc23f43341d19528b15aaf6e09f56975e1316 Mon Sep 17 00:00:00 2001 From: Ivan Gorinov Date: Fri, 25 May 2018 10:45:09 -0700 Subject: [PATCH 32/36] efi_selftest: check for buffer overflow in efi_get_variable Allocate a buffer on the stack instead of an array of uninitialized pointers; check if GetVariable writes past the end of the buffer. Signed-off-by: Ivan Gorinov Signed-off-by: Alexander Graf --- lib/efi_selftest/efi_selftest_variables.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/lib/efi_selftest/efi_selftest_variables.c b/lib/efi_selftest/efi_selftest_variables.c index f5e8eb6231c..146378fb9a2 100644 --- a/lib/efi_selftest/efi_selftest_variables.c +++ b/lib/efi_selftest/efi_selftest_variables.c @@ -49,7 +49,7 @@ static int execute(void) u32 attr; u8 v[16] = {0x5d, 0xd1, 0x5e, 0x51, 0x5a, 0x05, 0xc7, 0x0c, 0x35, 0x4a, 0xae, 0x87, 0xa5, 0xdf, 0x0f, 0x65,}; - u8 *data[EFI_ST_MAX_DATA_SIZE]; + u8 data[EFI_ST_MAX_DATA_SIZE]; u16 varname[EFI_ST_MAX_VARNAME_SIZE]; int flag; efi_guid_t guid; @@ -72,6 +72,22 @@ static int execute(void) efi_st_error("SetVariable failed\n"); return EFI_ST_FAILURE; } + data[3] = 0xff; + len = 3; + ret = runtime->get_variable(L"efi_st_var0", &guid_vendor0, + &attr, &len, data); + if (ret != EFI_SUCCESS) { + efi_st_error("GetVariable failed\n"); + return EFI_ST_FAILURE; + } + if (efi_st_memcmp(data, v + 4, 3)) { + efi_st_error("GetVariable returned wrong value\n"); + return EFI_ST_FAILURE; + } + if (data[3] != 0xff) { + efi_st_error("GetVariable wrote past the end of the buffer\n"); + return EFI_ST_FAILURE; + } /* Set variable 1 */ ret = runtime->set_variable(L"efi_st_var1", &guid_vendor1, EFI_VARIABLE_BOOTSERVICE_ACCESS, From e09159c86786929a728e3119726b10332226e6ea Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sat, 26 May 2018 10:32:27 +0200 Subject: [PATCH 33/36] efi_loader: avoid anonymous constants for AllocatePages Do not use anonymous constants when calling efi_allocage_pages. Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- cmd/bootefi.c | 6 ++++-- lib/efi_loader/efi_memory.c | 8 +++++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/cmd/bootefi.c b/cmd/bootefi.c index 806339823ff..707d159baca 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -143,11 +143,13 @@ static void *copy_fdt(void *fdt) /* Safe fdt location is at 128MB */ new_fdt_addr = fdt_ram_start + (128 * 1024 * 1024) + fdt_size; - if (efi_allocate_pages(1, EFI_RUNTIME_SERVICES_DATA, fdt_pages, + if (efi_allocate_pages(EFI_ALLOCATE_MAX_ADDRESS, + EFI_RUNTIME_SERVICES_DATA, fdt_pages, &new_fdt_addr) != EFI_SUCCESS) { /* If we can't put it there, put it somewhere */ new_fdt_addr = (ulong)memalign(EFI_PAGE_SIZE, fdt_size); - if (efi_allocate_pages(1, EFI_RUNTIME_SERVICES_DATA, fdt_pages, + if (efi_allocate_pages(EFI_ALLOCATE_MAX_ADDRESS, + EFI_RUNTIME_SERVICES_DATA, fdt_pages, &new_fdt_addr) != EFI_SUCCESS) { printf("ERROR: Failed to reserve space for FDT\n"); return NULL; diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c index d3302b66498..a4515c89812 100644 --- a/lib/efi_loader/efi_memory.c +++ b/lib/efi_loader/efi_memory.c @@ -337,7 +337,8 @@ void *efi_alloc(uint64_t len, int memory_type) uint64_t pages = (len + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT; efi_status_t r; - r = efi_allocate_pages(0, memory_type, pages, &ret); + r = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES, memory_type, pages, + &ret); if (r == EFI_SUCCESS) return (void*)(uintptr_t)ret; @@ -384,7 +385,8 @@ efi_status_t efi_allocate_pool(int pool_type, efi_uintn_t size, void **buffer) return EFI_SUCCESS; } - r = efi_allocate_pages(0, pool_type, num_pages, &t); + r = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES, pool_type, num_pages, + &t); if (r == EFI_SUCCESS) { struct efi_pool_allocation *alloc = (void *)(uintptr_t)t; @@ -515,7 +517,7 @@ int efi_memory_init(void) /* Request a 32bit 64MB bounce buffer region */ uint64_t efi_bounce_buffer_addr = 0xffffffff; - if (efi_allocate_pages(1, EFI_LOADER_DATA, + if (efi_allocate_pages(EFI_ALLOCATE_MAX_ADDRESS, EFI_LOADER_DATA, (64 * 1024 * 1024) >> EFI_PAGE_SHIFT, &efi_bounce_buffer_addr) != EFI_SUCCESS) return -1; From 3282614081ff3dcacd79a870475b332cbee3ff28 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 27 May 2018 16:45:09 +0200 Subject: [PATCH 34/36] efi_loader: efi_mem_carve_out should return s64 efi_mem_carve_out() is used to remove memory pages from a mapping. As the number of pages to be removed is a 64bit type the return type should be 64bit too. Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- lib/efi_loader/efi_memory.c | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c index a4515c89812..ec66af98ea8 100644 --- a/lib/efi_loader/efi_memory.c +++ b/lib/efi_loader/efi_memory.c @@ -68,23 +68,27 @@ static void efi_mem_sort(void) list_sort(NULL, &efi_mem, efi_mem_cmp); } -/* - * Unmaps all memory occupied by the carve_desc region from the - * list entry pointed to by map. +/** efi_mem_carve_out - unmap memory region * - * Returns EFI_CARVE_NO_OVERLAP if the regions don't overlap. - * Returns EFI_CARVE_OVERLAPS_NONRAM if the carve and map overlap, - * and the map contains anything but free ram. - * (only when overlap_only_ram is true) - * Returns EFI_CARVE_LOOP_AGAIN if the mapping list should be traversed - * again, as it has been altered - * Returns the number of overlapping pages. The pages are removed from - * the mapping list. + * @map: memory map + * @carve_desc: memory region to unmap + * @overlap_only_ram: the carved out region may only overlap RAM + * Return Value: the number of overlapping pages which have been + * removed from the map, + * EFI_CARVE_NO_OVERLAP, if the regions don't overlap, + * EFI_CARVE_OVERLAPS_NONRAM, if the carve and map overlap, + * and the map contains anything but free ram + * (only when overlap_only_ram is true), + * EFI_CARVE_LOOP_AGAIN, if the mapping list should be + * traversed again, as it has been altered. + * + * Unmaps all memory occupied by the carve_desc region from the list entry + * pointed to by map. * * In case of EFI_CARVE_OVERLAPS_NONRAM it is the callers responsibility - * to readd the already carved out pages to the mapping. + * to re-add the already carved out pages to the mapping. */ -static int efi_mem_carve_out(struct efi_mem_list *map, +static s64 efi_mem_carve_out(struct efi_mem_list *map, struct efi_mem_desc *carve_desc, bool overlap_only_ram) { @@ -183,7 +187,7 @@ uint64_t efi_add_memory_map(uint64_t start, uint64_t pages, int memory_type, carve_again = false; list_for_each(lhandle, &efi_mem) { struct efi_mem_list *lmem; - int r; + s64 r; lmem = list_entry(lhandle, struct efi_mem_list, link); r = efi_mem_carve_out(lmem, &newlist->desc, From d29e7824d782272f29dee68ea0ebb588257aacb4 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 27 May 2018 16:47:21 +0200 Subject: [PATCH 35/36] efi_loader: create handles from normal memory Handles are not used at runtime. They are freed by the firmware when the last protocol interface is uninstalled. So there is no reason to use EFI memory when creating handles. Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- lib/efi_loader/efi_boottime.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index b7ab2e8208e..50d311548e2 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -431,16 +431,15 @@ void efi_add_handle(struct efi_object *obj) efi_status_t efi_create_handle(efi_handle_t *handle) { struct efi_object *obj; - efi_status_t r; - r = efi_allocate_pool(EFI_ALLOCATE_ANY_PAGES, - sizeof(struct efi_object), - (void **)&obj); - if (r != EFI_SUCCESS) - return r; + obj = calloc(1, sizeof(struct efi_object)); + if (!obj) + return EFI_OUT_OF_RESOURCES; + efi_add_handle(obj); *handle = obj->handle; - return r; + + return EFI_SUCCESS; } /** From 80483b2ab62ca7cd200db445b6920ee96d17df88 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Sun, 3 Jun 2018 15:51:17 +0200 Subject: [PATCH 36/36] efi_loader: Fix warning in raw/cols query The code to determine rows / cols on the screen could potentially run into a case where it doesn't know how big the screen is. In that case, assume 80x25. Signed-off-by: Alexander Graf --- lib/efi_loader/efi_console.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/efi_loader/efi_console.c b/lib/efi_loader/efi_console.c index 0bfc24dbd98..ce66c935ecb 100644 --- a/lib/efi_loader/efi_console.c +++ b/lib/efi_loader/efi_console.c @@ -223,7 +223,7 @@ static int query_console_serial(int *rows, int *cols) static void query_console_size(void) { const char *stdout_name = env_get("stdout"); - int rows, cols; + int rows = 25, cols = 80; if (stdout_name && !strcmp(stdout_name, "vidconsole") && IS_ENABLED(CONFIG_DM_VIDEO)) {