On 01/31/2016 04:20 PM, Simon Glass wrote:
Hi Alexander,

On 14 January 2016 at 22:06, Alexander Graf <ag...@suse.de> wrote:
After booting has finished, EFI allows firmware to still interact with the OS
using the "runtime services". These callbacks live in a separate address space,
since they are available long after U-Boot has been overwritten by the OS.

This patch adds enough framework for arbitrary code inside of U-Boot to become
a runtime service with the right section attributes set. For now, we don't make
use of it yet though.

We could maybe in the future map U-boot environment variables to EFI variables
here.

Signed-off-by: Alexander Graf <ag...@suse.de>

---

v1 -> v2:

   - Fix runtime service sections
   - Add runtime detach
   - Enable runtime relocations
   - Add get_time
   - Fix relocation
   - Fix 32bit
   - Add am335x support
   - Move section definition to header
   - Add systab to runtime section
   - Add self-relocation hook table
   - Fix self-relocation
   - Relocate efi_runtime section early during bootup
   - Fix return values for a number of callbacks to be more UEFI compliant
   - Move to GPLv2+
---
  arch/arm/config.mk            |   4 +
  arch/arm/cpu/armv8/u-boot.lds |  16 +++
  arch/arm/cpu/u-boot.lds       |  30 +++++
  arch/arm/lib/sections.c       |   4 +
  board/ti/am335x/u-boot.lds    |  30 +++++
  common/board_r.c              |   4 +
  include/efi_loader.h          |  10 ++
  lib/efi_loader/efi_boottime.c |   6 +-
  lib/efi_loader/efi_runtime.c  | 300 ++++++++++++++++++++++++++++++++++++++++++
  9 files changed, 401 insertions(+), 3 deletions(-)
  create mode 100644 lib/efi_loader/efi_runtime.c
Reviewed-by: Simon Glass <s...@chromium.org>

A few nits.

diff --git a/arch/arm/config.mk b/arch/arm/config.mk
index 0550225..ecb956d 100644
--- a/arch/arm/config.mk
+++ b/arch/arm/config.mk
@@ -120,6 +120,10 @@ ifdef CONFIG_OF_EMBED
  OBJCOPYFLAGS += -j .dtb.init.rodata
  endif

+ifdef CONFIG_EFI_LOADER
+OBJCOPYFLAGS += -j .efi_runtime -j .efi_runtime_rel
+endif
+
  ifneq ($(CONFIG_IMX_CONFIG),)
  ifdef CONFIG_SPL
  ifndef CONFIG_SPL_BUILD
diff --git a/arch/arm/cpu/armv8/u-boot.lds b/arch/arm/cpu/armv8/u-boot.lds
index 4c12222..fd15ad5 100644
--- a/arch/arm/cpu/armv8/u-boot.lds
+++ b/arch/arm/cpu/armv8/u-boot.lds
@@ -42,6 +42,22 @@ SECTIONS

         . = ALIGN(8);

+       .efi_runtime : {
+                __efi_runtime_start = .;
+               *(efi_runtime_text)
+               *(efi_runtime_data)
+                __efi_runtime_stop = .;
+       }
+
+       .efi_runtime_rel : {
+                __efi_runtime_rel_start = .;
+               *(.relaefi_runtime_text)
+               *(.relaefi_runtime_data)
+                __efi_runtime_rel_stop = .;
+       }
+
+       . = ALIGN(8);
+
         .image_copy_end :
         {
                 *(.__image_copy_end)
diff --git a/arch/arm/cpu/u-boot.lds b/arch/arm/cpu/u-boot.lds
index d48a905..596a17d 100644
--- a/arch/arm/cpu/u-boot.lds
+++ b/arch/arm/cpu/u-boot.lds
@@ -89,6 +89,36 @@ SECTIONS

         . = ALIGN(4);

+       .__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)
+       }
+
+       . = ALIGN(4);
+
         .image_copy_end :
         {
                 *(.__image_copy_end)
diff --git a/arch/arm/lib/sections.c b/arch/arm/lib/sections.c
index a1205c3..6a94522 100644
--- a/arch/arm/lib/sections.c
+++ b/arch/arm/lib/sections.c
@@ -27,4 +27,8 @@ char __rel_dyn_start[0] 
__attribute__((section(".__rel_dyn_start")));
  char __rel_dyn_end[0] __attribute__((section(".__rel_dyn_end")));
  char __secure_start[0] __attribute__((section(".__secure_start")));
  char __secure_end[0] __attribute__((section(".__secure_end")));
+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")));
  char _end[0] __attribute__((section(".__end")));
diff --git a/board/ti/am335x/u-boot.lds b/board/ti/am335x/u-boot.lds
index 78f294a..a56cc82 100644
--- a/board/ti/am335x/u-boot.lds
+++ b/board/ti/am335x/u-boot.lds
@@ -59,6 +59,36 @@ SECTIONS

         . = ALIGN(4);

+       .__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)
+       }
+
+       . = ALIGN(4);
+
         .image_copy_end :
         {
                 *(.__image_copy_end)
diff --git a/common/board_r.c b/common/board_r.c
index 75ee43e..420e2c8 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -64,6 +64,7 @@
  #ifdef CONFIG_AVR32
  #include <asm/arch/mmu.h>
  #endif
+#include <efi_loader.h>

  DECLARE_GLOBAL_DATA_PTR;

@@ -176,6 +177,9 @@ static int initr_reloc_global_data(void)
         */
         gd->fdt_blob += gd->reloc_off;
  #endif
+#ifdef CONFIG_EFI_LOADER
+       efi_runtime_relocate(gd->relocaddr, NULL);
+#endif

         return 0;
  }
diff --git a/include/efi_loader.h b/include/efi_loader.h
index d314002..0f821ff 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -29,6 +29,7 @@

  #define EFI_EXIT(ret) efi_exit_func(ret);

+extern struct efi_runtime_services efi_runtime_services;
  extern struct efi_system_table systab;

  extern const struct efi_simple_text_output_protocol efi_con_out;
@@ -39,6 +40,9 @@ extern const efi_guid_t efi_guid_console_control;
  extern const efi_guid_t efi_guid_device_path;
  extern const efi_guid_t efi_guid_loaded_image;

+extern unsigned int __efi_runtime_start, __efi_runtime_stop;
+extern unsigned int __efi_runtime_rel_start, __efi_runtime_rel_stop;
+
  struct efi_class_map {
         const efi_guid_t *guid;
         const void *interface;
@@ -68,12 +72,18 @@ void *efi_load_pe(void *efi, struct efi_loaded_image 
*loaded_image_info);
  void efi_save_gd(void);
  void efi_restore_gd(void);
  efi_status_t efi_exit_func(efi_status_t ret);
+void efi_runtime_relocate(ulong offset, struct efi_mem_desc *map);
Function comment please.

  #define EFI_LOADER_POOL_SIZE (128 * 1024 * 1024)
  void *efi_loader_alloc(uint64_t len);

+#define EFI_RUNTIME_DATA __attribute__ ((section ("efi_runtime_data")))
+#define EFI_RUNTIME_TEXT __attribute__ ((section ("efi_runtime_text")))
+
  #else /* defined(EFI_LOADER) */

+#define EFI_RUNTIME_DATA
+#define EFI_RUNTIME_TEXT
  static inline void efi_restore_gd(void) { }

  #endif
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index 5756c9c..45217ef 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -36,7 +36,7 @@ static bool efi_is_direct_boot = true;
   * In most cases we want to pass an FDT to the payload, so reserve one slot of
   * config table space for it. The pointer gets populated by do_bootefi_exec().
   */
-static struct efi_configuration_table efi_conf_table[] = {
+static struct efi_configuration_table EFI_RUNTIME_DATA efi_conf_table[] = {
         {
                 .guid = EFI_FDT_GUID,
         },
@@ -741,10 +741,10 @@ static const struct efi_boot_services efi_boot_services = 
{
  };


-static uint16_t firmware_vendor[] =
+static uint16_t EFI_RUNTIME_DATA firmware_vendor[] =
         { 'D','a','s',' ','U','-','b','o','o','t',0 };

-struct efi_system_table systab = {
+struct efi_system_table EFI_RUNTIME_DATA systab = {
         .hdr = {
                 .signature = EFI_SYSTEM_TABLE_SIGNATURE,
                 .revision = 0x20005, /* 2.5 */
diff --git a/lib/efi_loader/efi_runtime.c b/lib/efi_loader/efi_runtime.c
new file mode 100644
index 0000000..b7aa1e9
--- /dev/null
+++ b/lib/efi_loader/efi_runtime.c
@@ -0,0 +1,300 @@
+/*
+ *  EFI application runtime services
+ *
+ *  Copyright (c) 2016 Alexander Graf
+ *
+ *  SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <common.h>
You use driver model so need <dm.h> too.

+#include <efi_loader.h>
+#include <command.h>
+#include <asm/global_data.h>
+#include <rtc.h>
+
+/* For manual relocation support */
+DECLARE_GLOBAL_DATA_PTR;
+
+static efi_status_t EFI_RUNTIME_TEXT efi_unimplemented(void);
+static efi_status_t EFI_RUNTIME_TEXT efi_device_error(void);
+static efi_status_t EFI_RUNTIME_TEXT efi_invalid_parameter(void);
+
+#if defined(CONFIG_ARM64)
+#define R_RELATIVE     1027
+#define R_MASK         0xffffffffULL
+#define IS_RELA                1
+#elif defined(CONFIG_ARM)
+#define R_RELATIVE     23
+#define R_MASK         0xffULL
+#else
+#error Need to add relocation awareness
+#endif
+
+struct elf_rel {
+       ulong *offset;
+       ulong info;
+};
+
+struct elf_rela {
+       ulong *offset;
+       ulong info;
+       long addend;
+};
Can you use elf.h?

I could, but elf.h has a hard distinction between 32bit and 64bit binaries while I really just want the one the binary is actually using at this specific moment.

So I could add #ifdefs on 32bit vs 64bit and then use the elf.h defines instead, but I'm not sure the code would look any more readable than it is now after that ;).


+
+/*
+ * EFI Runtime code lives in 2 stages. In the first stage, U-Boot and an EFI
+ * payload are running concurrently at the same time. In this mode, we can
+ * handle a good number of runtime callbacks
+ */
+
+static void efi_reset_system(enum efi_reset_type reset_type,
+                       efi_status_t reset_status, unsigned long data_size,
+                       void *reset_data)
+{
+       EFI_ENTRY("%d %lx %lx %p", reset_type, reset_status, data_size, 
reset_data);
+
+       switch (reset_type) {
+       case EFI_RESET_COLD:
+       case EFI_RESET_WARM:
+               do_reset(NULL, 0, 0, NULL);
+               break;
+       case EFI_RESET_SHUTDOWN:
+               /* We don't have anything to map this to */
+               break;
+       }
+
+       EFI_EXIT(EFI_SUCCESS);
+}
+
+static efi_status_t efi_get_time(struct efi_time *time,
+                         struct efi_time_cap *capabilities)
+{
+#ifdef CONFIG_CMD_DATE
+
+       struct rtc_time tm;
+       int r;
+#ifdef CONFIG_DM_RTC
Since this is a new service I don't think you need to support the old RTC API.

ok

Alex

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to