From: Ben Stoltz <sto...@google.com>

Add the required x86 glue code. This includes the initial start-up,
relocation and jumping to efi_main(). We also need to avoid fiddling with
interrupts.

Signed-off-by: Ben Stoltz <sto...@google.com>
Signed-off-by: Simon Glass <s...@chromium.org>
---

Changes in v2:
- Add ALIGN() before .dynamic in the linker script
- Add a blank line before return in the _relocate() function
- Add a comment as to why .hash has to be first in the linker script
- Add a comment as to why interrupt_init() must be skipped for EFI
- Drop unused DECLARE_GLOBAL_DATA_INIT
- Drop unused board_eth_init()
- Drop use of CONFIG_X86_64 since we don't support a 64-bit EFI application yet
- Fix spacing around operators
- Move 64-bit crt0 to a later patch
- Move crt0 and reloc files into arch/x86/lib/efi/
- Remove KEEP in the EFI linker script since garbage collection is not enabled
- Rename CONFIG_ARCH_EFI to CONFIG_EFI_APP
- Rename ImageBase to image_base
- Use SPDX for the EFI start and relocation code
- Use u-boot-app.efi instead of u-boot.efi

 Makefile                             |  6 +--
 arch/x86/Kconfig                     |  3 ++
 arch/x86/Makefile                    |  2 +
 arch/x86/cpu/Makefile                |  1 +
 arch/x86/cpu/efi/Makefile            |  8 +++
 arch/x86/cpu/efi/efi.c               | 42 ++++++++++++++++
 arch/x86/cpu/efi/elf_ia32_efi.lds    | 94 ++++++++++++++++++++++++++++++++++++
 arch/x86/cpu/efi/sdram.c             | 29 +++++++++++
 arch/x86/cpu/interrupts.c            |  6 +++
 arch/x86/include/asm/arch-efi/gpio.h | 10 ++++
 arch/x86/lib/efi/crt0-efi-ia32.S     | 52 ++++++++++++++++++++
 arch/x86/lib/efi/reloc_ia32.c        | 72 +++++++++++++++++++++++++++
 12 files changed, 322 insertions(+), 3 deletions(-)
 create mode 100644 arch/x86/cpu/efi/Makefile
 create mode 100644 arch/x86/cpu/efi/efi.c
 create mode 100644 arch/x86/cpu/efi/elf_ia32_efi.lds
 create mode 100644 arch/x86/cpu/efi/sdram.c
 create mode 100644 arch/x86/include/asm/arch-efi/gpio.h
 create mode 100644 arch/x86/lib/efi/crt0-efi-ia32.S
 create mode 100644 arch/x86/lib/efi/reloc_ia32.c

diff --git a/Makefile b/Makefile
index 3fb006b..6da9224 100644
--- a/Makefile
+++ b/Makefile
@@ -750,7 +750,7 @@ ifneq ($(CONFIG_SPL_TARGET),)
 ALL-$(CONFIG_SPL) += $(CONFIG_SPL_TARGET:"%"=%)
 endif
 ALL-$(CONFIG_REMAKE_ELF) += u-boot.elf
-ALL-$(CONFIG_EFI_APP) += u-boot.efi
+ALL-$(CONFIG_EFI_APP) += u-boot-app.efi
 
 ifneq ($(BUILD_ROM),)
 ALL-$(CONFIG_X86_RESET_VECTOR) += u-boot.rom
@@ -1079,8 +1079,8 @@ u-boot-dtb-tegra.bin: u-boot-nodtb-tegra.bin dts/dt.dtb 
FORCE
 endif
 endif
 
-OBJCOPYFLAGS_u-boot.efi := $(OBJCOPYFLAGS_EFI)
-u-boot.efi: u-boot FORCE
+OBJCOPYFLAGS_u-boot-app.efi := $(OBJCOPYFLAGS_EFI)
+u-boot-app.efi: u-boot FORCE
        $(call if_changed,zobjcopy)
 
 u-boot-img.bin: spl/u-boot-spl.bin u-boot.img FORCE
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index e8968a7..7e6e89c 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -11,6 +11,9 @@ choice
 config VENDOR_COREBOOT
        bool "coreboot"
 
+config VENDOR_EFI
+       bool "efi"
+
 config VENDOR_EMULATION
        bool "emulation"
 
diff --git a/arch/x86/Makefile b/arch/x86/Makefile
index 36a6018..d104a49 100644
--- a/arch/x86/Makefile
+++ b/arch/x86/Makefile
@@ -2,7 +2,9 @@
 # SPDX-License-Identifier:     GPL-2.0+
 #
 
+ifeq ($(CONFIG_EFI_APP),)
 head-y := arch/x86/cpu/start.o
+endif
 ifeq ($(CONFIG_SPL_BUILD),y)
 head-y += arch/x86/cpu/start16.o
 head-y += arch/x86/cpu/resetvec.o
diff --git a/arch/x86/cpu/Makefile b/arch/x86/cpu/Makefile
index 8a8e63e..5e058c0 100644
--- a/arch/x86/cpu/Makefile
+++ b/arch/x86/cpu/Makefile
@@ -14,6 +14,7 @@ obj-y += interrupts.o cpu.o cpu_x86.o call64.o
 
 obj-$(CONFIG_INTEL_BAYTRAIL) += baytrail/
 obj-$(CONFIG_SYS_COREBOOT) += coreboot/
+obj-$(CONFIG_EFI_APP) += efi/
 obj-$(CONFIG_QEMU) += qemu/
 obj-$(CONFIG_NORTHBRIDGE_INTEL_SANDYBRIDGE) += ivybridge/
 obj-$(CONFIG_NORTHBRIDGE_INTEL_IVYBRIDGE) += ivybridge/
diff --git a/arch/x86/cpu/efi/Makefile b/arch/x86/cpu/efi/Makefile
new file mode 100644
index 0000000..e091637
--- /dev/null
+++ b/arch/x86/cpu/efi/Makefile
@@ -0,0 +1,8 @@
+#
+# Copyright (c) 2015 Google, Inc
+#
+# SPDX-License-Identifier:     GPL-2.0+
+#
+
+obj-y += efi.o
+obj-y += sdram.o
diff --git a/arch/x86/cpu/efi/efi.c b/arch/x86/cpu/efi/efi.c
new file mode 100644
index 0000000..75ba0d4
--- /dev/null
+++ b/arch/x86/cpu/efi/efi.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2015 Google, Inc
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <fdtdec.h>
+#include <netdev.h>
+
+int arch_cpu_init(void)
+{
+#ifdef CONFIG_SYS_X86_TSC_TIMER
+       timer_set_base(rdtsc());
+#endif
+
+       return 0;
+}
+
+int board_early_init_f(void)
+{
+       return 0;
+}
+
+int print_cpuinfo(void)
+{
+       return default_print_cpuinfo();
+}
+
+void board_final_cleanup(void)
+{
+}
+
+int misc_init_r(void)
+{
+       return 0;
+}
+
+int arch_misc_init(void)
+{
+       return 0;
+}
diff --git a/arch/x86/cpu/efi/elf_ia32_efi.lds 
b/arch/x86/cpu/efi/elf_ia32_efi.lds
new file mode 100644
index 0000000..a83ddd0
--- /dev/null
+++ b/arch/x86/cpu/efi/elf_ia32_efi.lds
@@ -0,0 +1,94 @@
+/*
+ * U-Boot EFI linker script
+ *
+ * SPDX-License-Identifier:    bsd-2-clause
+ *
+ * Modified from usr/lib32/elf_ia32_efi.lds in gnu-efi
+ */
+
+#include <config.h>
+
+OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
+OUTPUT_ARCH(i386)
+ENTRY(_start)
+SECTIONS
+{
+       image_base = .;
+       .hash : { *(.hash) }    /* this MUST come first, EFI expects it */
+       . = ALIGN(4096);
+       .text :
+       {
+               *(.text)
+               *(.text.*)
+               *(.gnu.linkonce.t.*)
+       }
+       . = ALIGN(4096);
+       .sdata :
+       {
+               *(.got.plt)
+               *(.got)
+               *(.srodata)
+               *(.sdata)
+               *(.sbss)
+               *(.scommon)
+       }
+       . = ALIGN(4096);
+       .data :
+       {
+               *(.rodata*)
+               *(.data)
+               *(.data1)
+               *(.data.*)
+               *(.sdata)
+               *(.got.plt)
+               *(.got)
+               /*
+                * the EFI loader doesn't seem to like a .bss section, so we
+                * stick it all into .data:
+                */
+               *(.sbss)
+               *(.scommon)
+               *(.dynbss)
+               *(.bss)
+               *(COMMON)
+
+               /* U-Boot lists and device tree */
+               . = ALIGN(8);
+               *(SORT(.u_boot_list*));
+               . = ALIGN(8);
+               *(.dtb*);
+       }
+
+       . = ALIGN(4096);
+       .dynamic  : { *(.dynamic) }
+       . = ALIGN(4096);
+       .rel :
+       {
+               *(.rel.data)
+               *(.rel.data.*)
+               *(.rel.got)
+               *(.rel.stab)
+               *(.data.rel.ro.local)
+               *(.data.rel.local)
+               *(.data.rel.ro)
+               *(.data.rel*)
+               *(.rel.u_boot_list*)
+       }
+       . = ALIGN(4096);
+               .reloc :        /* This is the PECOFF .reloc section! */
+       {
+       *(.reloc)
+       }
+       . = ALIGN(4096);
+       .dynsym   : { *(.dynsym) }
+       . = ALIGN(4096);
+       .dynstr   : { *(.dynstr) }
+       . = ALIGN(4096);
+       /DISCARD/ :
+       {
+               *(.rel.reloc)
+               *(.eh_frame)
+               *(.note.GNU-stack)
+       }
+       .comment 0 : { *(.comment) }
+}
diff --git a/arch/x86/cpu/efi/sdram.c b/arch/x86/cpu/efi/sdram.c
new file mode 100644
index 0000000..5159944
--- /dev/null
+++ b/arch/x86/cpu/efi/sdram.c
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2015 Google, Inc
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <efi.h>
+#include <asm/u-boot-x86.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+ulong board_get_usable_ram_top(ulong total_size)
+{
+       return (ulong)efi_get_ram_base() + gd->ram_size;
+}
+
+int dram_init(void)
+{
+       /* gd->ram_size is set as part of EFI init */
+
+       return 0;
+}
+
+void dram_init_banksize(void)
+{
+       gd->bd->bi_dram[0].start = efi_get_ram_base();
+       gd->bd->bi_dram[0].size = CONFIG_EFI_RAM_SIZE;
+}
diff --git a/arch/x86/cpu/interrupts.c b/arch/x86/cpu/interrupts.c
index 3a9c2d4..a112938 100644
--- a/arch/x86/cpu/interrupts.c
+++ b/arch/x86/cpu/interrupts.c
@@ -242,6 +242,11 @@ int disable_interrupts(void)
 
 int interrupt_init(void)
 {
+       /*
+        * When running as an EFI application we are not in control of
+        * interrupts and should leave them alone.
+        */
+#ifndef CONFIG_EFI_APP
        /* Just in case... */
        disable_interrupts();
 
@@ -255,6 +260,7 @@ int interrupt_init(void)
 
        /* It is now safe to enable interrupts */
        enable_interrupts();
+#endif
 
        return 0;
 }
diff --git a/arch/x86/include/asm/arch-efi/gpio.h 
b/arch/x86/include/asm/arch-efi/gpio.h
new file mode 100644
index 0000000..f044f07
--- /dev/null
+++ b/arch/x86/include/asm/arch-efi/gpio.h
@@ -0,0 +1,10 @@
+/*
+ * Copyright (c) 2015 Google, Inc.
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef _X86_ARCH_GPIO_H_
+#define _X86_ARCH_GPIO_H_
+
+#endif /* _X86_ARCH_GPIO_H_ */
diff --git a/arch/x86/lib/efi/crt0-efi-ia32.S b/arch/x86/lib/efi/crt0-efi-ia32.S
new file mode 100644
index 0000000..30e5eb0
--- /dev/null
+++ b/arch/x86/lib/efi/crt0-efi-ia32.S
@@ -0,0 +1,52 @@
+/*
+ * crt0-efi-ia32.S - x86 EFI startup code.
+ *
+ * Copyright (C) 1999 Hewlett-Packard Co.
+ * Contributed by David Mosberger <dav...@hpl.hp.com>.
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:    BSD-3-Clause
+ */
+
+       .text
+       .align 4
+
+       .globl _start
+_start:
+       pushl %ebp
+       movl %esp,%ebp
+
+       pushl 12(%ebp)                  # copy "image" argument
+       pushl  8(%ebp)                  # copy "systab" argument
+
+       call 0f
+0:     popl %eax
+       movl %eax,%ebx
+
+       addl $image_base-0b,%eax        # %eax = ldbase
+       addl $_DYNAMIC-0b,%ebx          # %ebx = _DYNAMIC
+
+       pushl %ebx                      # pass _DYNAMIC as second argument
+       pushl %eax                      # pass ldbase as first argument
+       call _relocate
+       popl %ebx
+       popl %ebx
+       testl %eax,%eax
+       jne .exit
+       call efi_main           # call app with "image" and "systab" argument
+
+.exit: leave
+       ret
+
+       /*
+        * hand-craft a dummy .reloc section so EFI knows it's a relocatable
+        * executable:
+        */
+       .data
+dummy: .long   0
+
+#define IMAGE_REL_ABSOLUTE     0
+       .section .reloc
+       .long   dummy                                   /* Page RVA */
+       .long   10                                      /* Block Size (2*4+2) */
+       .word   (IMAGE_REL_ABSOLUTE << 12) +  0         /* reloc for dummy */
diff --git a/arch/x86/lib/efi/reloc_ia32.c b/arch/x86/lib/efi/reloc_ia32.c
new file mode 100644
index 0000000..4d68255
--- /dev/null
+++ b/arch/x86/lib/efi/reloc_ia32.c
@@ -0,0 +1,72 @@
+/*
+ * reloc_ia32.c - position independent x86 ELF shared object relocator
+ * Copyright (C) 1999 Hewlett-Packard Co.
+ * Contributed by David Mosberger <dav...@hpl.hp.com>.
+ *
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:    BSD-3-Clause
+ */
+
+#include <common.h>
+#include <efi.h>
+#include <elf.h>
+#include <asm/elf.h>
+
+efi_status_t _relocate(long ldbase, Elf32_Dyn *dyn, efi_handle_t image,
+                      struct efi_system_table *systab)
+{
+       long relsz = 0, relent = 0;
+       Elf32_Rel *rel = 0;
+       unsigned long *addr;
+       int i;
+
+       for (i = 0; dyn[i].d_tag != DT_NULL; ++i) {
+               switch (dyn[i].d_tag) {
+               case DT_REL:
+                       rel = (Elf32_Rel *)((unsigned long)dyn[i].d_un.d_ptr +
+                                                               ldbase);
+                       break;
+
+               case DT_RELSZ:
+                       relsz = dyn[i].d_un.d_val;
+                       break;
+
+               case DT_RELENT:
+                       relent = dyn[i].d_un.d_val;
+                       break;
+
+               case DT_RELA:
+                       break;
+
+               default:
+                       break;
+               }
+       }
+
+       if (!rel && relent == 0)
+               return EFI_SUCCESS;
+
+       if (!rel || relent == 0)
+               return EFI_LOAD_ERROR;
+
+       while (relsz > 0) {
+               /* apply the relocs */
+               switch (ELF32_R_TYPE(rel->r_info)) {
+               case R_386_NONE:
+                       break;
+
+               case R_386_RELATIVE:
+                       addr = (unsigned long *)(ldbase + rel->r_offset);
+                       *addr += ldbase;
+                       break;
+
+               default:
+                       break;
+               }
+               rel = (Elf32_Rel *)((char *)rel + relent);
+               relsz -= relent;
+       }
+
+       return EFI_SUCCESS;
+}
-- 
2.5.0.rc2.392.g76e840b

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

Reply via email to