]> git.sur5r.net Git - u-boot/commitdiff
Merge tag 'signed-efi-next' of git://github.com/agraf/u-boot
authorTom Rini <trini@konsulko.com>
Sun, 3 Jun 2018 16:27:56 +0000 (12:27 -0400)
committerTom Rini <trini@konsulko.com>
Sun, 3 Jun 2018 16:27:56 +0000 (12:27 -0400)
Patch queue for efi - 2018-06-03

A number of fixes and feature completeness work this time around:

  - Fix sunxi GOP reservation
  - Fix cursor position
  - Fix efi_get_variable
  - Allow more selftest parts to build on x86_64
  - Allow unaligned memory access on armv7
  - Implement ReinstallProtocolInterface
  - More sandbox preparation

43 files changed:
MAINTAINERS
Makefile
arch/arm/cpu/armv7/Makefile
arch/arm/cpu/armv7/sctlr.S [new file with mode: 0644]
arch/arm/include/asm/u-boot-arm.h
arch/sandbox/cpu/cpu.c
arch/sandbox/cpu/os.c
arch/sandbox/cpu/u-boot.lds
arch/sandbox/include/asm/setjmp.h [new file with mode: 0644]
arch/sandbox/lib/Makefile
arch/sandbox/lib/sections.c [new file with mode: 0644]
arch/x86/config.mk
arch/x86/include/asm/u-boot-x86.h
arch/x86/lib/Makefile
arch/x86/lib/bootm.c
cmd/bootefi.c
common/bootm.c
doc/DocBook/Makefile
doc/DocBook/efi.tmpl [new file with mode: 0644]
doc/README.uefi
drivers/video/sunxi/sunxi_de2.c
include/asm-generic/unaligned.h
include/bootm.h
include/efi_api.h
include/efi_loader.h
include/os.h
include/smbios.h
lib/efi_loader/Kconfig
lib/efi_loader/efi_bootmgr.c
lib/efi_loader/efi_boottime.c
lib/efi_loader/efi_console.c
lib/efi_loader/efi_image_loader.c
lib/efi_loader/efi_memory.c
lib/efi_loader/efi_runtime.c
lib/efi_loader/efi_smbios.c
lib/efi_loader/efi_variable.c
lib/efi_selftest/Kconfig
lib/efi_selftest/Makefile
lib/efi_selftest/efi_selftest_controllers.c
lib/efi_selftest/efi_selftest_manageprotocols.c
lib/efi_selftest/efi_selftest_textoutput.c
lib/efi_selftest/efi_selftest_unaligned.c [new file with mode: 0644]
lib/efi_selftest/efi_selftest_variables.c [new file with mode: 0644]

index f5ff57e87d4b22ad2a1336117a03d28cbb595557..642c448093859fd9cce3974933b019996419eaff 100644 (file)
@@ -342,6 +342,7 @@ EFI PAYLOAD
 M:     Alexander Graf <agraf@suse.de>
 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*
index 2995a198910968df6cf933cdd51b36a5b6215565..4592564cb4a3750d094dbe542ee145a1ef6ec3b4 100644 (file)
--- 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' -o -name '*.so' \) \
+               -type f -print | xargs rm -f
 
 # mrproper - Delete all generated files, including .config
 #
index 26056647df01f1db645bb9ee67c453df43b57dcc..4f4647c90ac1f7d291676b05c07c648c492db108 100644 (file)
@@ -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 (file)
index 0000000..bd56e41
--- /dev/null
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier:     GPL-2.0+ */
+/*
+ *  Routines to access the system control register
+ *
+ *  Copyright (c) 2018 Heinrich Schuchardt
+ */
+
+#include <linux/linkage.h>
+
+/*
+ * 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)
index 01c3ba87c3feb2258a69f4c317314f0d68f7036e..cc828c45045c369919b26ebe883e47bca6d81a3a 100644 (file)
@@ -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);
index d4ad020012e7835e365fcb62ea4f771f5c3ef958..cde0b055a673a2f5c897d9832cb6ead33d79d9ad 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/libfdt.h>
 #include <os.h>
 #include <asm/io.h>
+#include <asm/setjmp.h>
 #include <asm/state.h>
 #include <dm/root.h>
 
@@ -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)
+               ;
+}
index d76d0211a2d58063bfa8db233fe24040d0858ac1..5839932b00571538d3e8291694f3e6a692e14dae 100644 (file)
@@ -7,6 +7,7 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <getopt.h>
+#include <setjmp.h>
 #include <stdio.h>
 #include <stdint.h>
 #include <stdlib.h>
@@ -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);
+}
index f97abdfa0507b094798ed90fb3d71fff5154975a..3a6cf55eb99d4bc56a8178b3cd1ee3b1d96c226e 100644 (file)
@@ -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/include/asm/setjmp.h b/arch/sandbox/include/asm/setjmp.h
new file mode 100644 (file)
index 0000000..0fb1a11
--- /dev/null
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) 2018 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#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_ */
index 52eef2e662e70115699a4bf4775969c05ffe7a05..b4ff717e7849f7f9624269cf5c23d6bfcd0082b9 100644 (file)
@@ -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 (file)
index 0000000..697a816
--- /dev/null
@@ -0,0 +1,12 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2013 Albert ARIBAUD <albert.u.boot@aribaud.net>
+ *
+ */
+
+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")));
index 97db03deeed063b3e53783a4ad23d3e3add49b68..5f77f98e60a453676058a9726c0e357243b41689 100644 (file)
@@ -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_TARGET := --target=efi-app-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_TARGET := --target=efi-app-ia32
+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
index 9be45846a535bdb881b6b16306d43a17d795e309..2340ef83323d11a8fd4f7b6dab159acb10078915 100644 (file)
@@ -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);
 
index 51d451f9522be6fca84aadcd20840da275e2355f..5a64f6eddc7521199f8deb52db86cedf213c05b5 100644 (file)
@@ -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
index 533ba075bb1c79c8ce899a5b2c5dfe1e8d54a858..54c22fe6de3f50414446514d06bcda0412e5cfba 100644 (file)
@@ -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");
index 11b84c55289716517669ae8182430355057e5800..707d159baca8c6e565fb8199486b921bed6d26f3 100644 (file)
@@ -17,6 +17,7 @@
 #include <memalign.h>
 #include <asm/global_data.h>
 #include <asm-generic/sections.h>
+#include <asm-generic/unaligned.h>
 #include <linux/linkage.h>
 
 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.
  *
@@ -133,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;
@@ -370,6 +382,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) {
@@ -428,8 +443,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 */
index a0ffc1cd6790b0c6f36bfb7b52f5f291807be899..e789f6818aa30d043fea4526bef9806b535bf679 100644 (file)
@@ -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)
 {
index 820b1fb60f4d78e5433e5f2a9270ea8b60c38021..52576135138cc9539f7a92d40807bf6601b92048 100644 (file)
@@ -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 (file)
index 0000000..5daaae3
--- /dev/null
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+       "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
+
+<book id="UBootEFI">
+ <bookinfo>
+  <title>The U-Boot EFI subsystem</title>
+ </bookinfo>
+
+<toc></toc>
+
+  <chapter id="BootServices">
+     <title>Boot services</title>
+!Ilib/efi_loader/efi_boottime.c
+  </chapter>
+
+</book>
index 196e99994a332d086b0428fe8aae5d9b63af5c93..d4031ef8e86576df75e1a2779eb4d546f8fa4db0 100644 (file)
@@ -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
index a2303db9af57bb93e48f38a14173db26465c0307..4ed035d556a852d49903374a1d19bdf92838a772 100644 (file)
@@ -9,6 +9,7 @@
 #include <display.h>
 #include <dm.h>
 #include <edid.h>
+#include <efi_loader.h>
 #include <fdtdec.h>
 #include <fdt_support.h>
 #include <video.h>
@@ -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;
 }
 
index fd0255099aa279222b0a7a2b72c09ce1a3ff202c..3d33a5a063e8fa676039f567fb3a1f4b77e66f25 100644 (file)
@@ -20,4 +20,7 @@
 #error invalid endian
 #endif
 
+/* Allow unaligned memory access */
+void allow_unaligned(void);
+
 #endif
index 9e42e179878bbd001b1de77d691c5a085afa6c4f..0501414e0dc45b49be65a66d9d8953fe1f189eb1 100644 (file)
@@ -72,4 +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
index 64c27e494bcdf38341510b2d0a5b83d38e9a5a57..094be6edf9b055e6fc1cdf2cd66c97c6187aa709 100644 (file)
@@ -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 */
index ec000658f6de4220af3edfcbe9000e3a507faafb..c66252a7dd2accc4be5be86260f38fd49fc02281 100644 (file)
@@ -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 *
@@ -422,15 +429,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);
index 64e89a06c9498e24d84a00e734ce9f339ee657e8..c8e0f52d306345ac91d2a57d3dffe913e98e3764 100644 (file)
@@ -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
index 79880ef5b5c8cdb12acad700f245fe458d3d6c1a..97b9ddce23762eaabf18d36ce6241f84955ab4d5 100644 (file)
@@ -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);
 
index 2909e7696080d8ffb711e0f96ba28e5ead6848c1..df58e633d1c46e0f24e7e4698f6a112880766a63 100644 (file)
@@ -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
index 153e17375737bc7fbffeb008b5f1cf5f5f48e396..853358ab937874051eb01f401944516061957b65 100644 (file)
@@ -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;
 
index 5715a8b810e72959a76cc29f49e35ea05fa89e25..50d311548e2d4cc09d56102bd95884a29206b6d6 100644 (file)
@@ -10,7 +10,6 @@
 #include <efi_loader.h>
 #include <environment.h>
 #include <malloc.h>
-#include <asm/global_data.h>
 #include <linux/libfdt_env.h>
 #include <u-boot/crc.h>
 #include <bootm.h>
@@ -130,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
+ *
+ * A maximum of ten indent levels is supported. Higher indent levels will be
+ * truncated.
  *
- * @level      indent level
- * @return     indent string
+ * @level:             indent level
+ * Return Value:       A string for indenting with two spaces per level is
+ *                     returned.
  */
 static const char *indent_string(int level)
 {
@@ -161,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.
@@ -172,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)
 {
@@ -188,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
@@ -197,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)
 {
@@ -232,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)
 {
@@ -258,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)
 {
@@ -285,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,
@@ -309,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)
@@ -330,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,
@@ -361,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,
@@ -384,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)
 {
@@ -403,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)
 {
@@ -420,34 +422,33 @@ 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)
 {
        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;
 }
 
-/*
- * 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,
@@ -474,13 +475,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,
@@ -494,16 +495,18 @@ 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;
 }
 
-/*
- * 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)
 {
@@ -525,10 +528,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)
 {
@@ -539,11 +542,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)
 {
@@ -558,20 +561,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) (
@@ -610,20 +614,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) (
@@ -639,19 +642,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,
@@ -666,7 +669,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.
  *
@@ -699,16 +704,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)
@@ -740,17 +745,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,
@@ -760,17 +765,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,
@@ -817,8 +822,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
@@ -827,8 +832,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)
 {
@@ -839,15 +844,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)
 {
@@ -859,8 +864,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
@@ -869,8 +874,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)
 {
@@ -888,11 +893,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)
 {
@@ -906,11 +911,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)
@@ -926,11 +932,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)
@@ -940,13 +946,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,
@@ -974,19 +980,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,
@@ -1020,38 +1026,16 @@ out:
        return EFI_EXIT(r);
 }
 
-/*
- * Reinstall protocol interface.
- *
- * This function implements the ReinstallProtocolInterface service.
- * See the Unified Extensible Firmware Interface (UEFI) specification
- * for details.
+/**
+ * efi_get_drivers - get all drivers associated to a controller
  *
- * @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().
  *
- * @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,
@@ -1107,17 +1091,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,
@@ -1146,17 +1130,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,
@@ -1203,18 +1187,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,
@@ -1225,16 +1210,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,
@@ -1257,18 +1242,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,
@@ -1327,19 +1312,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,
@@ -1353,7 +1338,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];
@@ -1364,15 +1354,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)
@@ -1418,16 +1409,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)
@@ -1436,16 +1428,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,
@@ -1499,12 +1493,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)
@@ -1548,21 +1542,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,
@@ -1638,17 +1632,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,
@@ -1704,18 +1698,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,
@@ -1753,15 +1747,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)
 {
@@ -1775,8 +1769,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)
 {
@@ -1790,8 +1784,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
@@ -1801,9 +1795,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)
@@ -1865,15 +1859,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)
 {
@@ -1884,15 +1878,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)
 {
@@ -1901,18 +1895,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,
@@ -1924,18 +1918,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,
@@ -1971,18 +1965,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,
@@ -2034,17 +2029,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,
@@ -2095,19 +2090,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,
@@ -2142,17 +2137,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,
@@ -2183,17 +2178,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,
@@ -2259,17 +2255,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, ...)
@@ -2316,17 +2313,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, ...)
@@ -2373,17 +2372,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,
@@ -2394,16 +2393,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)
@@ -2413,16 +2412,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)
 {
@@ -2431,15 +2430,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,
@@ -2526,20 +2525,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,
@@ -2593,17 +2592,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,
@@ -2613,6 +2612,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,
@@ -2641,6 +2648,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,
@@ -2705,8 +2720,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
@@ -2716,11 +2731,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,
@@ -2773,14 +2788,59 @@ out:
        return EFI_EXIT(ret);
 }
 
-/*
- * Get all child controllers associated to a driver.
+/**
+ * efi_reinstall_protocol_interface - 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 Value:               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);
+}
+
+/**
+ * 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,
@@ -2835,17 +2895,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,
index d777db8a3ed13cb888eccae5fb2182ae42bd6e65..ce66c935ecbf7cff0eb019712c465c4cf2a7d2da 100644 (file)
@@ -12,8 +12,6 @@
 #include <stdio_dev.h>
 #include <video_console.h>
 
-static bool console_size_queried;
-
 #define EFI_COUT_MODE_2 2
 #define EFI_MAX_COUT_MODE 3
 
@@ -62,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;
@@ -79,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;
@@ -93,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;
 }
@@ -116,25 +124,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++;
@@ -194,6 +213,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 = 25, cols = 80;
+
+       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,
@@ -201,52 +265,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)
@@ -554,6 +578,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)
index b45f09591a5730231629fb441df00b54a40792c7..3cffe9ef46182dc0fe02bfbbb5e3303facea1563 100644 (file)
@@ -10,7 +10,6 @@
 #include <common.h>
 #include <efi_loader.h>
 #include <pe.h>
-#include <asm/global_data.h>
 
 const efi_guid_t efi_global_variable_guid = EFI_GLOBAL_VARIABLE_GUID;
 const efi_guid_t efi_guid_device_path = DEVICE_PATH_GUID;
@@ -90,11 +89,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 +107,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 +194,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 +238,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 +254,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 +285,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;
index 664c651db56292a63fce538b98f30c2976f5b026..ec66af98ea8f765e9be2dde26682f4c5c9379ad6 100644 (file)
@@ -10,7 +10,6 @@
 #include <inttypes.h>
 #include <malloc.h>
 #include <watchdog.h>
-#include <asm/global_data.h>
 #include <linux/list_sort.h>
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -69,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
+ *
+ * @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.
  *
- * 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.
+ * 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)
 {
@@ -184,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,
@@ -338,7 +341,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;
 
@@ -385,7 +389,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;
@@ -516,7 +521,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;
index 241090f6b4842639b2911032b1e0a731df27de97..65f2bcf1401adaca95fc4a0335b0d21e12498d1f 100644 (file)
@@ -10,7 +10,6 @@
 #include <dm.h>
 #include <efi_loader.h>
 #include <rtc.h>
-#include <asm/global_data.h>
 
 /* For manual relocation support */
 DECLARE_GLOBAL_DATA_PTR;
@@ -213,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,
@@ -445,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;
 }
@@ -465,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,
index 482436e2adb7c6469625238767eeb68176c0d178..7c3fc8af0b250f316ff37557fba4f914de07fb1f 100644 (file)
@@ -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 */
index 7e0e7f020ee12d428669d4027341703640a64c3a..90b637215e43db1fee9456cbdf73cab838903cdf 100644 (file)
@@ -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)
@@ -113,8 +101,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 +164,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;
@@ -209,8 +197,12 @@ efi_status_t EFIAPI efi_get_variable(s16 *variable_name,
        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(s16 *variable_name,
                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);
@@ -250,9 +242,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 +252,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)
index 3b5f3a1230b5b0af74bc7bb8ec7e8a74a9d9ca14..59f9f36801c54b0bf6862a1a8345a4c021479857 100644 (file)
@@ -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
index 80c43026458e33bc4969a7baf3b3eda72397ed42..4fe404d88d8e7ebe41239e08f972273543dd8bc8 100644 (file)
@@ -28,8 +28,13 @@ 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_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
index e30c11b1e458e2e9bf70c165635450323665c6ca..ceefa03444fc18787343e810d825981d42bac84f 100644 (file)
@@ -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;
index 3e4755c25e9133a2c1c2bb8500731834b6530057..44b8da3ba5d628337b32b56e9808fd3b303a1e6f 100644 (file)
@@ -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;
index 3533647fd493df8f0c161ffbc951d8afd4786679..a87f65e197fea1eea71a69524c2f68d54b53c295 100644 (file)
@@ -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;
 }
 
diff --git a/lib/efi_selftest/efi_selftest_unaligned.c b/lib/efi_selftest/efi_selftest_unaligned.c
new file mode 100644 (file)
index 0000000..f799c6d
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * efi_selftest_unaligned
+ *
+ * Copyright (c) 2018 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ *
+ * Test unaligned memory access on ARMv7.
+ */
+
+#include <efi_selftest.h>
+
+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,
+};
diff --git a/lib/efi_selftest/efi_selftest_variables.c b/lib/efi_selftest/efi_selftest_variables.c
new file mode 100644 (file)
index 0000000..146378f
--- /dev/null
@@ -0,0 +1,196 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * efi_selftest_variables
+ *
+ * Copyright (c) 2018 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * This unit test checks the following protocol services:
+ * ConnectController, DisconnectController,
+ * InstallProtocol, ReinstallProtocol, UninstallProtocol,
+ * OpenProtocol, CloseProtcol, OpenProtocolInformation
+ */
+
+#include <efi_selftest.h>
+
+#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;
+       }
+       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,
+                                   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,
+};